1 ADO.NET ADO.NET no es una revisión de ADO, pero presenta

Anuncio
ADO.NET
ADO.NET no es una revisión de ADO, pero presenta una nueva forma de trabajo
de datos, manejo desconectado de conjuntos de datos (reduciendo el trafico de
red) y XML como formato universal de transmisión de datos (manejo heterogéneo
de datos).
ADO.NET evoluciona desde ADO, tiene objetos comunes como Connection y
Command y nuevos objetos como DataSets, DataReaders, DataView y
DataAdapters.
Objeto Connection
Representa una conexión a un origen de datos. Las propiedades mínimas para
lograr una conexión son: DataSource, UserID y Password.
Los comandos viajan vía conexiones y vuelven sets resultados que retornan como
streams y pueden ser leídos por DataReaders o trabajados como DataSets.
Existen distintos tipos de objetos Connection es función del modelo de objetos a
usar:
Namespaces :
System.Data.Oledb
System.Data.Odbc
System.Data.SqlClient
System.Data.OracleClient
?? OledbConnection: vía Oledb
?? OdbcConnection: vía Odbc
?? SQLConnection: exclusivo para SqlServer (el propio de cada motor de
base de datos, existen distintos proveedores de ADO.NET, por ejemplo
OracleConnection para Oracle).
Objeto Command
Representa:
?? Una instrucción SQL (SELECT, INSERT, UPDATE, DELETE)
?? Una llamada a un stored procedure
Pueden tener parámetros de entrada y/o salida.
Existen distintos tipos de objetos Command es función del modelo de objetos a
usar:
?? OledbCommand: vía Oledb
?? OdbcCommand: vía Odbc
?? SQLCommand: exclusivo para SqlServer.
1
Objeto DataReader
Un DataReader es read-only y foward-only.
Un DataReader es retornado vía el método Execute de un objeto Command.
Existen distintos tipos de objetos DataReader es función del modelo de objetos a
usar:
?? OledbDataReader: vía Oledb
?? OdbcDataReader: vía Odbc
?? SQLDataReader: exclusivo para SqlServer.
Objeto DataSet
Es un objeto genérico (se usa el mismo para los distintos namespaces).
Representa a datos cacheados, con un comportamiento similar al de una base de
datos.
Contiene:
?? Tablas
?? Columnas
?? Relaciones
?? Restricciones
?? Datos
Los datos pueden provenir de:
?? Una base de datos
?? Un archivo XML
?? Desde código
?? De ingreso de datos del usuario
Para obtener un dataset, se usa el objeto DataAdapter y su método Fill.
Objeto DataView
Representa un vista personalizada de una tabla.
Objeto DataAdapter
Representa “una consola personalizada”, que oculta los detalles del trabajo de
conexiones y comandos. Este objeto se encarga del recupero y actualización de
datos, entre el DataSet y el origen de datos.
Tiene propiedades para indicar los distintos comandos:
2
??
??
??
??
UpdateCommand
InsertCommand
DeleteCommand
SelectCommand
Existen distintos tipos de objetos DataAdapter es función del modelo de objetos a
usar:
?? OledbDataAdapter: vía Oledb
?? OdbcDataAdapter: vía Odbc
?? SQLDataAdapter: exclusivo para SqlServer.
Uso de namespaces
En C#:
Using System.Data.Odbc;
En VB.NET:
Import System.Data.Odbc
Conexión a un origen de datos vía Odbc
En C#:
public void CreateOdbcConnection()
{
string myConnString = "DRIVER={SQL
Server};SERVER=MyServer;Trusted_connection=yes;DATABASE=northwind;";
OdbcConnection myConnection = new OdbcConnection(myConnString);
myConnection.Open();
}
En VB.NET:
Public Sub CreateOdbcConnection()
Dim myConnString As String = "DRIVER={SQL
Server};SERVER=MyServer;Trusted_connection=yes;DATABASE=northwind;"
Dim myConnection As New OdbcConnection(myConnString)
myConnection.Open()
End Sub
Conexión a un origen de datos vía Oledb
En C#:
public void CreateOleDbConnection()
{
string myConnString = "Provider=SQLOLEDB;Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=SSPI;Connect Timeout=30";
OleDbConnection myConnection = new OleDbConnection(myConnString);
myConnection.Open();
}
En VB.NET:
3
Public Sub CreateOleDbConnection()
Dim myConnString As String = "Provider=SQLOLEDB;Data
Source=localhost;Initial Catalog=Northwind;Integrated
Security=SSPI;Connect Timeout=30"
Dim myConnection As New OleDbConnection(myConnString)
myConnection.Open()
End Sub
Conexión a un origen de datos vía SqlClient
En C#:
public void CreateSqlConnection()
{
string myConnectString = "Persist Security Info=False;Integrated
Security=SSPI;database=northwind;server=mySQLServer;Connect Timeout=30";
SqlConnection myConnection = new SqlConnection(myConnectString);
myConnection.Open();
}
En VB.NET:
Public Sub CreateSqlConnection()
Dim myConnectString As String = "Persist Security
Info=False;Integrated
Security=SSPI;database=northwind;server=mySQLServer;Connect Timeout=30"
Dim myConnection As New SqlConnection(myConnectString)
myConnection.Open()
End Sub
Uso de DataSets para leer datos vía Odbc
Para poblar un DataSet es necesario:
?? Abrir una conexión a un origen de datos
?? Crear un comando e indicarle la instrucción SQL de selección
?? Crear un DataAdapter y usar su método Fill para poblar el DataSet
?? Cerrar la conexión
En C#:
OdbcConnection nwindConn = new OdbcConnection("Driver={SQL
Server};Server=localhost;" +
"Trusted_Connection=yes;Database=northwind");
OdbcCommand selectCMD = new OdbcCommand("SELECT CustomerID, CompanyName
FROM Customers", nwindConn);
OdbcDataAdapter custDA = new OdbcDataAdapter();
custDA.SelectCommand = selectCMD;
nwindConn.Open();
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
4
nwindConn.Close();
En VB.NET:
Dim nwindConn As OdbcConnection = New OdbcConnection("Driver={SQL
Server};Server=localhost;" & _
"Trusted_Connection=yes;Database=northwind")
Dim selectCMD As OdbcCommand = New OdbcCommand("SELECT CustomerID,
CompanyName FROM Customers", nwindConn)
Dim custDA As OdbcDataAdapter = New OdbcDataAdapter
custDA.SelectCommand = selectCMD
nwindConn.Open()
Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")
nwindConn.Close()
Uso de DataSets para leer datos vía Oledb
En C#:
OleDbConnection nwindConn = new OleDbConnection("Provider=SQLOLEDB;Data
Source=localhost;" +
"Integrated Security=SSPI;Initial Catalog=northwind");
OleDbCommand selectCMD = new OleDbCommand("SELECT CustomerID, CompanyName
FROM Customers", nwindConn);
OleDbDataAdapter custDA = new OleDbDataAdapter();
custDA.SelectCommand = selectCMD;
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
En VB.NET:
Dim nwindConn As OleDbConnection = New
OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;" & _
"Integrated Security=SSPI;Initial Catalog=northwind")
Dim selectCMD As OleDbCommand = New OleDbCommand("SELECT CustomerID,
CompanyName FROM Customers", nwindConn)
Dim custDA As OleDbDataAdapter = New OleDbDataAdapter
custDA.SelectCommand = selectCMD
Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")
Uso de DataSets para leer datos vía SqlClient
En C#:
5
SqlConnection nwindConn = new SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
SqlCommand selectCMD = new SqlCommand("SELECT CustomerID, CompanyName
FROM Customers", nwindConn);
SqlDataAdapter custDA = new SqlDataAdapter();
custDA.SelectCommand = selectCMD;
nwindConn.Open();
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
nwindConn.Close();
En VB.NET:
Dim nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")
Dim selectCMD As SqlCommand = New SqlCommand("SELECT CustomerID,
CompanyName FROM Customers", nwindConn)
Dim custDA As SqlDataAdapter = New SqlDataAdapter
custDA.SelectCommand = selectCMD
nwindConn.Open()
Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "Customers")
nwindConn.Close()
Llenar un DataSet con varias tablas
Un dataset puede ser poblado con varias tablas, del mismo origen de datos o de
varios orígenes de datos.
En el ejemplo de código siguiente se llena una lista de clientes a partir de la base
de datos Northwind de Microsoft SQL Server 2000 y una lista de pedidos a partir
de la base de datos Northwind almacenada en Microsoft® Access 2000. Las
tablas de datos llenas se relacionan entre sí mediante DataRelation, con lo que se
puede mostrar una lista de clientes con los pedidos que ha realizado cada uno.
En VB.NET:
Dim custConn As SqlConnection= New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;" & _
"Initial Catalog=northwind;")
Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM
Customers", custConn)
Dim orderConn As OleDbConnection = New
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
6
"Data Source=c:\Program Files\Microsoft Office\" & _
"Office\Samples\northwind.mdb;")
Dim orderDA As OleDbDataAdapter = New OleDbDataAdapter("SELECT * FROM
Orders", orderConn)
custConn.Open()
orderConn.Open()
Dim custDS As DataSet = New DataSet()
custDA.Fill(custDS, "Customers")
orderDA.Fill(custDS, "Orders")
custConn.Close()
orderConn.Close()
Dim custOrderRel As DataRelation = custDS.Relations.Add("CustOrders", _
custDS.Tables("Customers").Columns("CustomerID"), _
custDS.Tables("Orders").Columns("CustomerID"))
Dim pRow, cRow As DataRow
For Each pRow In custDS.Tables("Customers").Rows
Console.WriteLine(pRow("CustomerID").ToString())
For Each cRow In pRow.GetChildRows(custOrderRel)
Console.WriteLine(vbTab & cRow("OrderID").ToString())
Next
Next
En C#:
SqlConnection custConn = new SqlConnection("Data
Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind;");
SqlDataAdapter custDA = new SqlDataAdapter("SELECT * FROM Customers",
custConn);
OleDbConnection orderConn = new
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=c:\\Program Files\\Microsoft
Office\\Office\\Samples\\northwind.mdb;");
OleDbDataAdapter orderDA = new OleDbDataAdapter("SELECT * FROM Orders",
orderConn);
custConn.Open();
orderConn.Open();
DataSet custDS = new DataSet();
custDA.Fill(custDS, "Customers");
orderDA.Fill(custDS, "Orders");
custConn.Close();
orderConn.Close();
7
DataRelation custOrderRel = custDS.Relations.Add("CustOrders",
custDS.Tables["Customers"].Columns["CustomerID"],
custDS.Tables["Orders"].Columns["CustomerID"]);
foreach (DataRow pRow in custDS.Tables["Customers"].Rows)
{
Console.WriteLine(pRow["CustomerID"]);
foreach (DataRow cRow in pRow.GetChildRows(custOrderRel))
Console.WriteLine("\t" + cRow["OrderID"]);
}
Uso de DataViews
Un DataView permite crear diferentes vistas de los datos almacenados en un
DataTable. Mediante una DataView puede exponer los datos de una tabla con
distintos criterios de ordenación y puede filtrar los datos por el estado de fila o
basándose en una expresión de filtro.
Un DataView proporciona una vista dinámica de los datos cuyo contenido,
ordenación y pertenencia reflejan cambios en la DataTable subyacente a medida
que se producen. Esto es distinto del método Select de la DataTable , que
devuelve una matriz de DataRow de una tabla por un filtro o un criterio de
ordenación determinado y cuyo contenido refleja cambios en la tabla subyacente,
pero cuya pertenencia y ordenación siguen siendo estáticas.
Una DataView es similar a la vista suministrada por una base de datos, pero
difiere considerablemente de una vista de base de datos en el sentido de que la
DataView no se puede tratar como una tabla y no puede proporcionar una vista de
tablas combinadas. Tampoco puede excluir columnas que existen en la tabla de
origen ni puede anexar columnas, como columnas de cálculo, que no existen en la
tabla de origen.
Crear DataView
Hay dos formas de crear un DataView. Puede utilizar el constructor DataView o
puede crear una referencia a la propiedad DefaultView de la DataTable. El
constructor DataView puede estar vacío, o puede tomar también DataTable como
único argumento o DataTable junto con el criterio de filtro o de ordenación, y un
filtro de estado de fila.
Como el índice de un DataView se crea cuando se crea el DataView y cuando se
modifica alguna de las propiedades Sort, RowFilter o RowStateFilter, conseguirá
los mejores resultados si suministra cualquier criterio inicial de ordenación o
filtrado como argumentos del constructor cuando crea el DataView. La creación de
un DataView sin especificar el criterio de ordenación o de filtrado y el posterior
establecimiento de las propiedades Sort, RowFilter o RowStateFilter hace que el
índice se cree al menos dos veces: una cuando se crea el DataView y otra cuando
se modifica alguna propiedad de ordenación o de filtrado.
8
En el ejemplo de código siguiente se muestra cómo crear una DataView con el
constructor DataView. Con la DataTable se suministran un RowFilter, una
columna Sort y un DataViewRowState .
En VB.NET:
Dim custDV As DataView = New DataView(custDS.Tables("Customers"), _
"Country = 'USA'", _
"ContactName", _
DataViewRowState.CurrentRows)
En C#:
DataView custDV = new DataView(custDS.Tables["Customers"],
"Country = 'USA'",
"ContactName",
DataViewRowState.CurrentRows);
En el siguiente ejemplo de código se muestra cómo obtener una referencia al
DataView predeterminado de un DataTable mediante la propiedad DefaultView
de la tabla.
En VB.NET:
Dim custDV As DataView = custDS.Tables("Customers").DefaultView
En C#:
DataView custDV = custDS.Tables["Customers"].DefaultView;
Ordenar y filtrar datos mediante DataView
Un DataView ofrece varias posibilidades para ordenar y filtrar datos de un
DataTable:
??
Con la propiedad Sort puede especificar criterios simples o múltiples de
ordenación de columnas e incluir parámetros ASC (ascendente) y DESC
(descendente).
?? Puede utilizar la propiedad ApplyDefaultSort para crear automáticamente
un criterio de ordenación, en sentido ascendente, basándose en la columna
o las columnas de clave principal de la tabla. ApplyDefaultSort sólo se
aplica cuando la propiedad Sort es una referencia nula o una cadena vacía
y cuando la tabla tiene definida una clave principal.
?? Con la propiedad RowFilter puede especificar subconjuntos de filas
basándose en sus valores de columna.
Si desea devolver los resultados de una consulta determinada en los datos,
en lugar de proporcionar una vista dinámica de un subconjunto de los
datos, para conseguir el máximo rendimiento utilice los métodos Find o
FindRows de la DataView en lugar de establecer la propiedad RowFilter.
El establecimiento de la propiedad RowFilter hace que se vuelva a generar
el índice de los datos, lo que agrega sobrecarga a la aplicación y reduce el
rendimiento. Los métodos Find y FindRows aprovechan el índice actual,
sin necesidad de volver a generarlo.
9
??
Con la propiedad RowStateFilter puede especificar qué versiones de fila
desea ver. Por ejemplo, si el RowStateFilter está establecido como
DataViewRowState.Deleted, el DataView expondrá la versión de fila
Original de todas las filas Deleted porque no hay ninguna versión de fila
Current. Con la propiedad RowVersion de la DataRowView puede
determinar qué versión de una fila se está exponiendo.
En la siguiente tabla se muestran las opciones de DataViewRowState .
DataViewRowState
Descripción
La versión de fila Current de todas las filas Unchanged,
CurrentRows
Added y Modified. Éste es el valor predeterminado.
La versión de fila Current de todas las filas Added.
Added
La versión de fila Original de todas las filas Deleted.
Deleted
La versión de fila Current de todas las filas Modified.
ModifiedCurrent
La versión de fila Original de todas las filas Modified.
ModifiedOriginal
Ninguna fila.
None
La versión de fila Original de todas las filas Unchanged,
OriginalRows
Modified y Deleted.
La versión de fila Current de todas las filas Unchanged.
Unchanged
En el siguiente ejemplo de código se crea una vista que muestra todos los
productos cuyas unidades en existencia son menor o igual que el nivel de nuevo
pedido, ordenados en primer lugar por ID. de proveedor y después por nombre de
producto.
En VB.NET:
Dim prodView As DataView = New DataView(prodDS.Tables("Products"), _
"UnitsInStock <= ReorderLevel", _
"SupplierID, ProductName", _
DataViewRowState.CurrentRows)
En C#:
DataView prodView = new DataView(prodDS.Tables["Products"],
"UnitsInStock <= ReorderLevel",
"SupplierID, ProductName",
DataViewRowState.CurrentRows);
Mostrar datos en un DataGrid desde un DataSet
Para mostrar datos en el cliente, puede usar los data-bound controls:
?? DataGrid
?? DataList
?? DataRepeater
Por ejemplo, para enlazar un DataSet en un DataGrid, hay que asignar la
propiedad DataSource del DataGrid , y luego llamar al método DataBind .
10
En C#:
dgAuthors.DataSource = ds;
dgAuthors.DataBind();
Mostrar datos en un DataGrid desde un DataView
Crea un DataView de la tabla Authors del DataSet, y filtra por el campo state =
‘CA’, y lo asigna al DataGrid.
En VB.NET:
Dim dv as DataView
dv = New DataView (ds.Tables(“Authors”))
dv.RowFilter = “state = ‘CA’”
dgAuthors.DataSource = dv
dgAuthors.DataBind()
Uso de Stored Procedures (sp)
Para llamar a un procedimiento almacenado (sp), asigne el valor
StoredProcedure a la propiedad CommandType del objeto Command. Al
asignar el valor StoredProcedure a CommandType , puede usar la colección
Parameters para definir parámetros, como se muestra en el ejemplo siguiente.
Nota: OdbcCommand requiere que el usuario proporcione la
sintaxis de llamada CALL de ODBC completa al llamar a un
procedimiento almacenado.
vía SqlClient en VB.NET
Dim nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;"Initial Catalog=northwind")
Dim salesCMD As SqlCommand = New SqlCommand("SalesByCategory", nwindConn)
salesCMD.CommandType = CommandType.StoredProcedure
Dim myParm As SqlParameter = salesCMD.Parameters.Add("@CategoryName",
SqlDbType.NVarChar, 15)
myParm.Value = "Beverages"
nwindConn.Open()
Dim myReader As SqlDataReader = salesCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", myReader.GetName(0), myReader.GetName(1))
Do While myReader.Read()
Console.WriteLine("{0}, ${1}", myReader.GetString(0),
myReader.GetDecimal(1))
Loop
myReader.Close()
11
nwindConn.Close()
Via Oledb en VB.NET
Dim nwindConn As OleDbConnection = New
OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;Integrated
Security=SSPI;" & "Initial Catalog=northwind")
Dim salesCMD As OleDbCommand = New OleDbCommand("SalesByCategory",
nwindConn)
salesCMD.CommandType = CommandType.StoredProcedure
Dim myParm As OleDbParameter = salesCMD.Parameters.Add("@CategoryName",
OleDbType.VarChar, 15)
myParm.Value = "Beverages"
nwindConn.Open()
Dim myReader As OleDbDataReader = salesCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", myReader.GetName(0), myReader.GetName(1))
Do While myReader.Read()
Console.WriteLine("{0}, ${1}", myReader.GetString(0),
myReader.GetDecimal(1))
Loop
myReader.Close()
nwindConn.Close()
Via Odbc en VB.NET
Dim nwindConn As OdbcConnection = New OdbcConnection("Driver={SQL
Server};Server=localhost;Trusted_Connection=yes;" & _
"Database=northwind")
nwindConn.Open()
Dim salesCMD As OdbcCommand = New OdbcCommand("{ CALL SalesByCategory(?)
}", nwindConn)
salesCMD.CommandType = CommandType.StoredProcedure
Dim myParm As OdbcParameter = salesCMD.Parameters.Add("@CategoryName",
OdbcType.VarChar, 15)
myParm.Value = "Beverages"
Dim myReader As OdbcDataReader = salesCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", myReader.GetName(0), myReader.GetName(1))
Do While myReader.Read()
Console.WriteLine("{0}, ${1}", myReader.GetString(0),
myReader.GetDecimal(1))
Loop
myReader.Close()
nwindConn.Close()
12
Un objeto Parameter se puede crear mediante el constructor Parameter o al
llamar al método Add de la colección Parameters de Command.
Parameters.Add acepta como entrada argumentos del constructor o cualquier
objeto Parameter ya existente. Al establecer como una referencia nula el valor de
Value de un objeto Parameter, debe usar DBNull.Value .
En el caso de parámetros que no sean de entrada (Input), debe asignar a la
propiedad ParameterDirection un valor que especifique cuál es el tipo de
parámetro: InputOutput, Output o ReturnValue. En el ejemplo siguiente se
muestra la diferencia en la creación de parámetros Input, Output y ReturnValue.
vía SqlClie nt en VB.NET
Dim sampleCMD As SqlCommand = New SqlCommand("SampleProc", nwindConn)
sampleCMD.CommandType = CommandType.StoredProcedure
Dim sampParm As SqlParameter = sampleCMD.Parameters.Add("RETURN_VALUE",
SqlDbType.Int)
sampParm.Direction = ParameterDirection.ReturnValue
sampParm = sampleCMD.Parameters.Add("@InputParm", SqlDbType.NVarChar, 12)
sampParm.Value = "Sample Value"
sampParm = sampleCMD.Parameters.Add("@OutputParm", SqlDbType.NVarChar,
28)
sampParm.Direction = ParameterDirection.Output
nwindConn.Open()
Dim sampReader As SqlDataReader = sampleCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", sampReader.GetName(0),
sampReader.GetName(1))
Do While sampReader.Read()
Console.WriteLine("{0}, {1}", sampReader.GetInt32(0),
sampReader.GetString(1))
Loop
sampReader.Close()
nwindConn.Close()
Console.WriteLine(" @OutputParm: {0}",
sampleCMD.Parameters("@OutputParm").Value)
Console.WriteLine("RETURN_VALUE: {0}",
sampleCMD.Parameters("RETURN_VALUE").Value)
Via Oledb en VB.NET
Dim sampleCMD As OleDbCommand = New OleDbCommand("SampleProc", nwindConn)
sampleCMD.CommandType = CommandType.StoredProcedure
Dim sampParm As OleDbParameter = sampleCMD.Parameters.Add("RETURN_VALUE",
OleDbType.Integer)
13
sampParm.Direction = ParameterDirection.ReturnValue
sampParm = sampleCMD.Parameters.Add("@InputParm", OleDbType.VarChar, 12)
sampParm.Value = "Sample Value"
sampParm = sampleCMD.Parameters.Add("@OutputParm", OleDbType.VarChar, 28)
sampParm.Direction = ParameterDirection.Output
nwindConn.Open()
Dim sampReader As OleDbDataReader = sampleCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", sampReader.GetName(0),
sampReader.GetName(1))
Do While sampReader.Read()
Console.WriteLine("{0}, {1}", sampReader.GetInt32(0),
sampReader.GetString(1))
Loop
sampReader.Close()
nwindConn.Close()
Console.WriteLine(" @OutputParm: {0}",
sampleCMD.Parameters("@OutputParm").Value)
Console.WriteLine("RETURN_VALUE: {0}",
sampleCMD.Parameters("RETURN_VALUE").Value)
Via Odbc en VB.NET
Dim sampleCMD As OdbcCommand = New OdbcCommand("{ ? = CALL SampleProc(?,
?) }", nwindConn)
sampleCMD.CommandType = CommandType.StoredProcedure
Dim sampParm As OdbcParameter = sampleCMD.Parameters.Add("RETURN_VALUE",
OdbcType.Int)
sampParm.Direction = ParameterDirection.ReturnValue
sampParm = sampleCMD.Parameters.Add("@InputParm", OdbcType.VarChar, 12)
sampParm.Value = "Sample Value"
sampParm = sampleCMD.Parameters.Add("@OutputParm", OdbcType.VarChar, 28)
sampParm.Direction = ParameterDirection.Output
nwindConn.Open()
Dim sampReader As OdbcDataReader = sampleCMD.ExecuteReader()
Console.WriteLine("{0}, {1}", sampReader.GetName(0),
sampReader.GetName(1))
Do While sampReader.Read()
Console.WriteLine("{0}, {1}", sampReader.GetInt32(0),
sampReader.GetString(1))
Loop
sampReader.Close()
14
nwindConn.Close()
Console.WriteLine(" @OutputParm: {0}",
sampleCMD.Parameters("@OutputParm").Value)
Console.WriteLine("RETURN_VALUE: {0}",
sampleCMD.Parameters("RETURN_VALUE").Value)
Utilizar parámetros con SqlCommand
Al utilizar parámetros con SqlCommand, los nombres de los parámetros
agregados a la colección Parameters deben coincidir con los definidos en el
encabezado del procedimiento almacenado. El proveedor de datos de .NET
Framework para SQL Server trata los parámetros del procedimiento almacenado
como parámetros con nombre y busca los marcadores de parámetros que
coinciden con sus nombres.
El proveedor de datos de .NET Framework para SQL Server no permite usar el
marcador de posición de signo de interrogación de cierre (?) para pasar
parámetros a una instrucción SQL o a un procedimiento almacenado. En este
caso, debe usar parámetros con nombre, como se muestra en el ejemplo
siguiente.
SELECT * FROM Customers WHERE CustomerID = @CustomerID
Utilizar parámetros con OleDbCommand o con OdbcCommand
Al utilizar parámetros con OleDbCommand o con OdbcCommand, el orden de
los parámetros agregados a la colección Parameters debe coincidir con el de los
parámetros definidos en el procedimiento almacenado. El proveedor de datos de
.NET Framework para OLE DB y el proveedor de datos de .NET Framework para
ODBC consideran a los parámetros de un procedimiento almacenado como
marcadores de posición y aplican los valores de los parámetros en orden.
Además, los parámetros de valores devueltos deben ser los primeros que se
agreguen a la colección Parameters.
El proveedor de datos de .NET Framework para OLE DB y el proveedor de datos
de .NET Framework para ODBC no permiten usar parámetros con nombre para
pasar parámetros a una instrucción SQL o a un procedimiento almacenado. En
este caso, se debe usar el marcador de posición de signo interrogación de cierre
(?) como se muestra en el ejemplo s iguiente.
SELECT * FROM Customers WHERE CustomerID = ?
Por eso, el orden en que se agregan los objetos Parameter a la colección
Parameters debe coincidir exactamente con la posición del marcador de posición
de interrogación de cierre correspondiente al parámetro.
15
Derivar la información de parámetros
Los parámetros también se pueden derivar de un procedimiento almacenado
mediante la clase CommandBuilder . Las clases SqlCommandBuilder y
OleDbCommandBuilder proporcionan un método estático, DeriveParameters,
que llena automáticamente la colección Parameters de un objeto Command con
la información de los parámetros de un procedimiento almacenado. Tenga en
cuenta que DeriveParameters sobrescribirá toda la información de los parámetros
que pueda tener anteriormente el objeto Command.
Para derivar la información de los parámetros, es necesario visitar nuevamente el
origen de datos y recuperar la información. Si la información de los parámetros se
conoce en tiempo de diseño, puede mejorar el rendimiento de la aplicación si
establece los parámetros con los valores correspondientes de forma explícita.
En el ejemplo de código siguiente se muestra cómo llenar la colección
Parameters de un objeto Command con CommandBuilder.DeriveParameters.
Dim nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Initial Catalog=Northwind;Integrated Security=SSPI;")
Dim salesCMD As SqlCommand = New SqlCommand("Sales By Year", nwindConn)
salesCMD.CommandType = CommandType.StoredProcedure
nwindConn.Open()
SqlCommandBuilder.DeriveParameters(salesCMD)
nwindConn.Close()
Stored procedures de actualización
Las instrucciones SQL que modifican datos (por ejemplo INSERT, UPDATE o
DELETE) no devuelven ninguna fila. De la misma forma, muchos procedimientos
almacenados realizan alguna acción pero no devuelven filas. Para ejecutar
comandos que no devuelven filas, debe crear un objeto Command con el
comando SQL y Connection adecuados (y con los Parameters que sean
necesarios), y usar el método ExecuteNonQuery del objeto Command.
El método ExecuteNonQuery devuelve un entero que representa el número de
filas que se ven afectadas por la instrucción o por el procedimiento almacenado
que se haya ejecutado. Si se ejecutan varias instrucciones, el valor devuelto es la
suma de los registros afectados por todas las instrucciones ejecutadas.
En el ejemplo de código siguiente se ejecuta una instrucción INSERT para insertar
un registro en una base de datos con el método ExecuteNonQuery.
vía SqlClient en VB.NET
Dim nwindConn As SqlConnection = New SqlConnection("Data
Source=localhost;Integrated Security=SSPI;" & _
"Initial Catalog=northwind")
nwindConn.Open()
16
Dim insertStr As String = "INSERT INTO Customers (CustomerID,
CompanyName) Values('NWIND', 'Northwind Traders')"
Dim insertCMD As SqlCommand = New SqlCommand(insertStr, nwindConn)
Dim recordsAffected As Int32 = insertCMD.ExecuteNonQuery()
Via SqlClient en C#
SqlConnection nwindConn = new SqlConnection("Data
Source=localhost;Integrated Security=SSPI;" +
"Initial Catalog=northwind");
nwindConn.Open();
string insertStr = "INSERT INTO Customers (CustomerID, CompanyName)
Values('NWIND', 'Northwind Traders')";
SqlCommand insertCMD = new SqlCommand(insertStr, nwindConn);
Int32 recordsAffected = insertCMD.ExecuteNonQuery();
En el ejemplo de código siguiente se ejecuta el procedimiento almacenado que no
devuelve ninguna fila, por lo que se usa el método ExecuteNonQuery, aunque el
procedimiento almacenado reciba un parámetro de entrada, y devuelva un
parámetro de salida y un valor devuelto.
En el caso del objeto OleDbCommand, se debe agregar en primer lugar el
parámetro ReturnValue a la colección Parameters.
vía SqlClient en VB.NET
Dim insertCatCMD As SqlCommand = New SqlCommand("InsertCategory" ,
nwindConn)
insertCatCMD.CommandType = CommandType.StoredProcedure
Dim workParm As SqlParameter
workParm = insertCatCMD.Parameters.Add("@RowCount", SqlDbType.Int)
workParm.Direction = ParameterDirection.ReturnValue
workParm = insertCatCMD.Parameters.Add("@CategoryName", SqlDbType.NChar,
15)
workParm = insertCatCMD.Parameters.Add("@Identity", SqlDbType.Int)
workParm.Direction = ParameterDirection.Output
insertCatCMD.Parameters("@CategoryName").Value = "New Category"
insertCatCMD.ExecuteNonQuery()
Dim catID As Int32 = CInt(insertCatCMD.Parameters("@Identity").Value)
Dim rowCount As Int32 = CInt(insertCatCMD.Parameters("@RowCount").Value)
Via SqlClient en C#
SqlCommand insertCatCMD = new SqlCommand("InsertCategory" , nwindConn);
insertCatCMD.CommandType = CommandType.StoredProcedure;
SqlParameter workParm;
17
workParm = insertCatCMD.Parameters.Add("@RowCount", SqlDbType.Int);
workParm.Direction = ParameterDirection.ReturnValue;
workParm = insertCatCMD.Parameters.Add("@CategoryName", SqlDbType.NChar,
15);
workParm = insertCatCMD.Parameters.Add("@Identity", SqlDbType.Int);
workParm.Direction = ParameterDirection.Output;
insertCatCMD.Parameters["@CategoryName"].Value = "New Category";
insertCatCMD.ExecuteNonQuery();
Int32 catID = (Int32)insertCatCMD.Parameters["@Identity"].Value;
Int32 rowCount = (Int32)insertCatCMD.Parameters["@RowCount"].Value;
Uso de DataReaders
El beneficio del uso de DataSets, es que provee una vista desconectada de la
base de datos. Para las aplicaciones web, generalmente se necesitan por cada
request, operaciones simples y cortas que muestren datos.
Cuando no es necesario mantener una vista completa de un conjunto de datos, la
opción a usar es un DataReader , que recupera una secuencia de datos de sólo
avance y de sólo lectura desde una base de datos. Los resultados se devuelven
cuando se ejecuta la consulta y se almacenan en el búfer de red del cliente hasta
que el usuario los solicita mediante el método Read del objeto DataReader. El uso
de DataReader puede mejorar el rendimiento de la aplicación mediante la
recuperación de los datos tan pronto como estén disponibles, en lugar de tener
que esperar a que se devuelvan todos los resultados de la consulta, y (de forma
predeterminada) mediante el almacenamiento de una sola fila cada vez en
memoria, lo que reduce la sobrecarga del sistema.
Después de crear una instancia del objeto Command, para crear un DataReader
debe llamar a Command.ExecuteReader con el fin de recuperar las filas desde
un origen de datos, como se muestra en el ejemplo siguiente.
Via SqlClient en VB.NET
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
Via SqlClient en C#
SqlDataReader myReader = myCommand.ExecuteReader();
Puede usar el método Read del objeto DataReader para obtener una fila a partir
de los resultados de una consulta. Para tener acceso a cada columna de la fila
devuelta, puede pasar al DataReader el nombre o referencia numérica de la
columna en cuestión. Sin embargo, el mejor rendimiento se logra con los métodos
que ofrece DataReader y que permiten tener acceso a los valores de las
columnas en sus tipos de datos nativos ( GetDateTime , GetDouble, GetGuid,
GetInt32, etcétera). Para obtener una lista de métodos de descriptor de acceso
con tipo, vea OleDbDataReader (Clase) y SqlDataReader (Clase). Si se usan los
18
métodos de descriptor de acceso con tipo cuando se conoce el tipo de datos
subyacente, se reduce el número de conversiones de tipo necesarias para
recuperar el valor de una columna.
Nota La versión de Windows Server 2003 de .NET Framework
incluye una propiedad adicional para DataReader, HasRows, que
permite determinar si DataReader ha devuelto resultados antes de la
lectura del mismo.
En el ejemplo de código siguiente se itera por un objeto DataReader y se
devuelven dos columnas de cada fila.
Via SqlClient en VB.NET
If myReader.HasRows Then
Do While myReader.Read()
Console.WriteLine(vbTab & "{0}" & vbTab & "{1}",
myReader.GetInt32(0), myReader.GetString(1))
Loop
Else
Console.WriteLine("No rows returned.")
End If
myReader.Close()
Via SqlClient en C#
if (myReader.HasRows)
while (myReader.Read())
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0),
myReader.GetString(1));
else
Console.WriteLine("No rows returned.");
myReader.Close();
DataReader proporciona una secuencia de datos sin búfer que permite a la lógica
de los procedimientos procesar eficazmente y de forma secuencial los resultados
procedentes de un origen de datos. DataReader es la mejor opción cuando se
trata de recuperar grandes cantidades de datos, ya que éstos no se almacenan en
la memoria caché.
Siempre debe llamar al método Close cuando haya terminado de usar el objeto
DataReader.
Si Command contiene parámetros de salida o valores devueltos, éstos no estarán
disponibles hasta que se cierre el DataReader.
Tenga en cuenta que mientras está abierto un DataReader, éste usa de forma
exclusiva el objeto Connection. Por eso no podrá ejecutar ningún comando en el
objeto Connection, ni siquiera el de creación de otro DataReader, hasta que se
cierre el DataReader original.
19
Uso de DataReaders para múltiples conjuntos de resultados
Si se devuelven varios conjuntos de resultados, DataReader proporciona el
método NextResult, que permite recorrer en iteración los conjuntos de resultados,
como se muestra en el ejemplo siguiente.
Via SqlClient en VB.NET
Dim myCMD As SqlCommand = New SqlCommand("SELECT CategoryID, CategoryName
FROM Categories; SELECT EmployeeID, LastName FROM Employees", nwindConn)
nwindConn.Open()
Dim myReader As SqlDataReader = myCMD.ExecuteReader()
Dim fNextResult As Boolean = True
Do Until Not fNextResult
Console.WriteLine(vbTab & myReader.GetName(0) & vbTab &
myReader.GetName(1))
Do While myReader.Read()
Console.WriteLine(vbTab & myReader.GetInt32(0) & vbTab &
myReader.GetString(1))
Loop
fNextResult = myReader.NextResult()
Loop
myReader.Close()
nwindConn.Close()
Via SqlClient en C#
SqlCommand myCMD = new SqlCommand("SELECT CategoryID, CategoryName FROM
Categories; SELECT EmployeeID, LastName FROM Employees", nwindConn);
nwindConn.Open();
SqlDataReader myReader = myCMD.ExecuteReader();
do
{
Console.WriteLine("\t{0}\t{1}", myReader.GetName(0),
myReader.GetName(1));
while (myReader.Read())
Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0),
myReader.GetString(1));
} while (myReader.NextResult());
myReader.Close();
nwindConn.Close();
20
Descargar