Se utiliza para este ejemplo el lenguaje de consulta SQL, el lenguaje de programación C# y el IDE Microsoft Visual Studio Community.
Situación o Negocio
Para no complicar el ejemplo se utiliza dos tablas con pocos campos.
En una universidad los estudiantes estudian una carrera de ingeniería. De los estudiantes se saben su DNI y Nombre. De la carrera de ingeniería el nombre.
La relación de estas tablas es de 1:N (Uno a varios). Un estudiante solo estudia una carrera de ingeniería y una carrera de ingeniería posee varios estudiantes.
Script – Sql
CREATE TABLE engineering
(
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR(255) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
UNIQUE NONCLUSTERED ([Name] ASC)
)
CREATE TABLE student
(
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[DNI] VARCHAR(255) NOT NULL,
[Name] VARCHAR(255) NOT NULL,
[IdEngineering] BIGINT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
UNIQUE NONCLUSTERED ([DNI] ASC),
CONSTRAINT [FK] FOREIGN KEY ([IdEngineering])
REFERENCES [dbo].[engineering] ([Id])
ON DELETE CASCADE
ON UPDATE CASCADE
)
Paso 1- Abrir Visual Studio
- Crear un proyecto de tipo Class Library. (FILE -> new -> Proyect)
- Ctrl + Shift + A
- Crear el fichero de Sql (mdf)
Paso 2
- Crear el fichero app.config y escribir la cadena de conexión con la base de datos
- Crear la clase Connection
class Connection
{
public static SqlConnection SqlConnectionProvider
{
get
{
var cnx =
ConfigurationManager.ConnectionStrings[
"ClassDataSetBlog.Properties.Settings.DatabaseDataSetConnectionString"].ConnectionString;
return new SqlConnection(cnx);
}
}
}
Paso 3
Se crea las clases que mapean con las tablas de la base de datos (engineering y student).
public class Engineering
{
public long Id { get; set; }
public string Name { get; set; }
}
public class Student
{
public long Id { get; set; }
public string Dni { get; set; }
public string Name { get; set; }
public long IdEngineering { get; set; }
}
Paso 4
Crear las clase Adapter de cada tabla y mapearlo con las clases del Paso 3.
Se utiliza las clases SqlDataAdapter y SqlCommand.
El SqlCommand tiene la propiedad CommandText que recibe una query de Sql o cuando se inicializa el comando puede recibir en su constructor una query
Ejemplo:
_adapter.DeleteCommand = new SqlCommand("DELETE FROM engineering WHERE Id = " + item.Id, connection);
En este caso se va a guardar las query en un fichero de recursos. Ctrl + Shift + AEste recurso nos sirve como un diccionario de códigos SQL
Crear la clase AdapterEngineering y AdapterStudent
public class AdapterEngineering
{
private readonly SqlDataAdapter _adapter;
public AdapterEngineering()
{
_adapter = new SqlDataAdapter();
}
public int Insert(Engineering item)
{
var connection = Connection.SqlConnectionProvider;
_adapter.InsertCommand = new SqlCommand(ResourceQueryEngineering.Insert, connection);
var parameter = new SqlParameter(ResourceQueryEngineering.Parameter_Name, item.Name);
_adapter.InsertCommand.Parameters.Add(parameter);
connection.Open();
var value = _adapter.InsertCommand.ExecuteNonQuery();
connection.Close();
return value;
}
public int Update(Engineering item)
{
var connection = Connection.SqlConnectionProvider;
_adapter.UpdateCommand = new SqlCommand(ResourceQueryEngineering.Update, connection);
SqlParameter[] parameters =
{
new SqlParameter(ResourceQueryEngineering.Parameter_Name, item.Name),
new SqlParameter(ResourceQueryEngineering.Parameter_Id, item.Id)
};
_adapter.InsertCommand.Parameters.AddRange(parameters);
connection.Open();
var value = _adapter.UpdateCommand.ExecuteNonQuery();
connection.Close();
return value;
}
public int Delete(Engineering item)
{
var connection = Connection.SqlConnectionProvider;
_adapter.DeleteCommand = new SqlCommand(ResourceQueryEngineering.Delete, connection);
var parameter = new SqlParameter(ResourceQueryEngineering.Parameter_Id, item.Id);
_adapter.DeleteCommand.Parameters.Add(parameter);
connection.Open();
var value = _adapter.DeleteCommand.ExecuteNonQuery();
connection.Close();
return value;
}
public List Fill()
{
var connection = Connection.SqlConnectionProvider;
var datatable = new DataTable();
_adapter.SelectCommand = new SqlCommand(ResourceQueryEngineering.Select, connection);
_adapter.Fill(datatable);
return datatable.Rows.Count == 0 ? new List() :
(from DataRow variable in datatable.Rows
select new Engineering
{
Id = (long)variable[0],
Name = (string)variable[1]
}).ToList();
}
public List QueryEngineeringCountStudent()
{
var connection = Connection.SqlConnectionProvider;
var datatable = new DataTable();
_adapter.SelectCommand = new SqlCommand(ResourceQueryEngineering.SelectEngineeringCountStudent, connection);
_adapter.Fill(datatable);
return datatable.Rows.Count == 0 ? new List() :
(from DataRow variable in datatable.Rows
select new EngineeringCountStudentDto
{
EngineeringName = (string)variable[0],
Count = (int)variable[1]
}).ToList();
}
}
Paso 6Se tiene el diseño, las consultas y las funciones básicas de los CRUD de las tablas para gestionar la información de la base de datos. Ahora pasaremos a testear estas acciones con las pruebas unitarias.
- Ctrl + Shift + A
[TestMethod]
public void TestEgineering()
{
var adapter = new AdapterEngineering();
for (int i = 0; i < 10; i++)
adapter.Insert(new Engineering{
Name = "Engineering " + i
});
var list = adapter.Fill();
int delete = adapter.Delete(list[0]);
Assert.AreEqual(1, delete);
}
Conclusiones Se realiza paso por paso un pequeño ejemplo de cómo utilizar nuestro viejo DataSet y se realiza pruebas unitarias.
Espero que les haya gustado y recuerden que mi objetivo es publicar varias formas de comunicación de una Aplicación con un gestor de base de datos. Próximamente les pondré como aplicar el patrón repositorio.
ADO.NET + Patrón Repositorio + C#
Se despide
Ing. YAM