.NET Framework
ADO.NET
Buscar..
Introducción
ADO (ActiveX Data Objects) .Net es una herramienta proporcionada por Microsoft que proporciona acceso a fuentes de datos como SQL Server, Oracle y XML a través de sus componentes. Las aplicaciones de front-end de .Net pueden recuperar, crear y manipular datos, una vez que se conectan a una fuente de datos a través de ADO.Net con los privilegios adecuados.
ADO.Net proporciona una arquitectura sin conexión. Es un enfoque seguro para interactuar con una base de datos, ya que la conexión no tiene que mantenerse durante toda la sesión.
Observaciones
Una nota sobre la parametrización de SQL con Parameters.AddWithValue
: AddWithValue
nunca es un buen punto de partida. Ese método se basa en inferir el tipo de datos de lo que se pasa. Con esto, puede terminar en una situación en la que la conversión impide que su consulta utilice un índice . Tenga en cuenta que algunos tipos de datos de SQL Server, como char
/ varchar
(sin la "n") o la date
, no tienen un tipo de datos .NET correspondiente. En esos casos, se debe usar Add
con el tipo de datos correcto .
Ejecutando sentencias SQL como un comando
// Uses Windows authentication. Replace the Trusted_Connection parameter with
// User Id=...;Password=...; to use SQL Server authentication instead. You may
// want to find the appropriate connection string for your server.
string connectionString = @"Server=myServer\myInstance;Database=myDataBase;Trusted_Connection=True;"
string sql = "INSERT INTO myTable (myDateTimeField, myIntField) " +
"VALUES (@someDateTime, @someInt);";
// Most ADO.NET objects are disposable and, thus, require the using keyword.
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
// Use parameters instead of string concatenation to add user-supplied
// values to avoid SQL injection and formatting issues. Explicitly supply datatype.
// System.Data.SqlDbType is an enumeration. See Note1
command.Parameters.Add("@someDateTime", SqlDbType.DateTime).Value = myDateTimeVariable;
command.Parameters.Add("@someInt", SqlDbType.Int).Value = myInt32Variable;
// Execute the SQL statement. Use ExecuteScalar and ExecuteReader instead
// for query that return results (or see the more specific examples, once
// those have been added).
connection.Open();
command.ExecuteNonQuery();
}
Nota 1: Consulte la enumeración de SqlDbType para la variación específica de MSFT SQL Server.
Nota 2: Consulte la enumeración de MySqlDbType para la variación específica de MySQL.
Buenas prácticas - Ejecución de sentencias SQL
public void SaveNewEmployee(Employee newEmployee)
{
// best practice - wrap all database connections in a using block so they are always closed & disposed even in the event of an Exception
// best practice - retrieve the connection string by name from the app.config or web.config (depending on the application type) (note, this requires an assembly reference to System.configuration)
using(SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString))
{
// best practice - use column names in your INSERT statement so you are not dependent on the sql schema column order
// best practice - always use parameters to avoid sql injection attacks and errors if malformed text is used like including a single quote which is the sql equivalent of escaping or starting a string (varchar/nvarchar)
// best practice - give your parameters meaningful names just like you do variables in your code
using(SqlCommand sc = new SqlCommand("INSERT INTO employee (FirstName, LastName, DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)", con))
{
// best practice - always specify the database data type of the column you are using
// best practice - check for valid values in your code and/or use a database constraint, if inserting NULL then use System.DbNull.Value
sc.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar, 200){Value = newEmployee.FirstName ?? (object) System.DBNull.Value});
sc.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar, 200){Value = newEmployee.LastName ?? (object) System.DBNull.Value});
// best practice - always use the correct types when specifying your parameters, Value is assigned to a DateTime instance and not a string representation of a Date
sc.Parameters.Add(new SqlParameter("@dateOfBirth", SqlDbType.Date){ Value = newEmployee.DateOfBirth });
// best practice - open your connection as late as possible unless you need to verify that the database connection is valid and wont fail and the proceeding code execution takes a long time (not the case here)
con.Open();
sc.ExecuteNonQuery();
}
// the end of the using block will close and dispose the SqlConnection
// best practice - end the using block as soon as possible to release the database connection
}
}
// supporting class used as parameter for example
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
Mejores prácticas para trabajar con ADO.NET
- La regla de oro es abrir la conexión por un tiempo mínimo. Cierre la conexión explícitamente una vez que finalice la ejecución del procedimiento, el objeto de conexión volverá al grupo de conexiones. Tamaño máximo del conjunto de conexiones predeterminado = 100. Como el conjunto de conexiones mejora el rendimiento de la conexión física a SQL Server. Conexión de agrupación en SQL Server
- Envuelva todas las conexiones de la base de datos en un bloque de uso para que siempre estén cerradas y eliminadas incluso en el caso de una Excepción. Consulte Uso de la declaración (Referencia de C #) para obtener más información sobre el uso de declaraciones
- Recupere las cadenas de conexión por nombre desde app.config o web.config (dependiendo del tipo de aplicación)
- Esto requiere una referencia de ensamblaje a
System.configuration
- Consulte Cadenas de conexión y archivos de configuración para obtener información adicional sobre cómo estructurar su archivo de configuración.
- Esto requiere una referencia de ensamblaje a
- Siempre use parámetros para los valores entrantes a
- Evitar los ataques de inyección sql
- Evite los errores si se usa texto con formato incorrecto, como incluir una comilla simple que es el equivalente en sql de escapar o iniciar una cadena (varchar / nvarchar)
- Permitir que el proveedor de la base de datos reutilice los planes de consulta (no es compatible con todos los proveedores de la base de datos) lo que aumenta la eficiencia
- Al trabajar con parámetros.
- El tipo de parámetros de SQL y la falta de coincidencia de tamaño es una causa común de error de inserción / actualización / selección
- Dale a tus parámetros de Sql nombres significativos al igual que lo haces con las variables en tu código
- Especifique el tipo de datos de la base de datos de la columna que está utilizando, esto garantiza que no se usen los tipos de parámetros incorrectos, lo que podría dar lugar a resultados inesperados
- Valide los parámetros entrantes antes de pasarlos al comando (como dice el dicho, " basura dentro, basura fuera "). Valide los valores entrantes lo antes posible en la pila
- Utilice los tipos correctos cuando asigne sus valores de parámetros, por ejemplo: no asigne el valor de cadena de DateTime, en su lugar, asigne una instancia de DateTime real al valor del parámetro
- Especifique el tamaño de los parámetros de tipo cadena. Esto se debe a que SQL Server puede reutilizar los planes de ejecución si los parámetros coinciden en tipo y tamaño. Usa -1 para MAX
- No utilice el método AddWithValue , la razón principal es que es muy fácil olvidar especificar el tipo de parámetro o la precisión / escala cuando sea necesario. Para información adicional, vea ¿Podemos dejar de usar AddWithValue ya?
- Cuando se utilizan conexiones de base de datos
- Abra la conexión lo más tarde posible y ciérrela tan pronto como sea posible. Esta es una guía general cuando se trabaja con cualquier recurso externo
- Nunca comparta instancias de conexión de base de datos (ejemplo: tener un host singleton una instancia compartida de tipo
SqlConnection
). Haga que su código siempre cree una nueva instancia de conexión de base de datos cuando sea necesario y luego haga que el código de llamada lo elimine y "deséchelo" cuando termine. La razón de esto es- La mayoría de los proveedores de bases de datos tienen algún tipo de agrupación de conexiones, por lo que crear nuevas conexiones administradas es barato
- Elimina cualquier error futuro si el código comienza a trabajar con varios subprocesos
Usando interfaces comunes para abstraer clases específicas
var providerName = "System.Data.SqlClient"; //Oracle.ManagedDataAccess.Client, IBM.Data.DB2
var connectionString = "{your-connection-string}";
//you will probably get the above two values in the ConnectionStringSettings object from .config file
var factory = DbProviderFactories.GetFactory(providerName);
using(var connection = factory.CreateConnection()) { //IDbConnection
connection.ConnectionString = connectionString;
connection.Open();
using(var command = connection.CreateCommand()) { //IDbCommand
command.CommandText = "{query}";
using(var reader = command.ExecuteReader()) { //IDataReader
while(reader.Read()) {
...
}
}
}
}