Gegevens verwerken
Vóór de introductie van MARS (Multiple Active Result Sets) moesten ontwikkelaars meerdere verbindingen of cursors aan de serverzijde gebruiken om bepaalde scenario's op te lossen. Bovendien waren er bij het gebruik van meerdere verbindingen in een transactionele situatie gebonden verbindingen (met sp_getbindtoken en sp_bindsession) vereist. In de volgende scenario's ziet u hoe u een mars-verbinding gebruikt in plaats van meerdere verbindingen.
Meerdere opdrachten gebruiken met MARS
In de volgende consoletoepassing ziet u hoe u twee SqlDataReader objecten gebruikt met twee SqlCommand objecten en één SqlConnection object waarvoor MARS is ingeschakeld.
Opmerking
In het voorbeeld wordt één verbinding met de AdventureWorks-database geopend. Er wordt een SqlCommand object gemaakt met behulp van een SqlDataReader object. Terwijl de lezer wordt gebruikt, wordt een tweede SqlDataReader geopend, waarbij gegevens uit de eerste SqlDataReader worden gebruikt als invoer voor de WHERE-component voor de tweede lezer.
Notitie
In het volgende voorbeeld wordt de voorbeelddatabase AdventureWorks gebruikt die is opgenomen in SQL Server. Bij het verbindingsreeks in de voorbeeldcode wordt ervan uitgegaan dat de database is geïnstalleerd en beschikbaar is op de lokale computer. Wijzig de verbindingsreeks indien nodig voor uw omgeving.
Option Strict On
Option Explicit On
Imports System
Imports System.Data
Imports System.Data.SqlClient
Module Module1
Sub Main()
' By default, MARS is disabled when connecting
' to a MARS-enabled host.
' It must be enabled in the connection string.
Dim connectionString As String = GetConnectionString()
Dim vendorID As Integer
Dim vendorCmd As SqlCommand
Dim productCmd As SqlCommand
Dim productReader As SqlDataReader
Dim vendorSQL As String = & _
"SELECT VendorId, Name FROM Purchasing.Vendor"
Dim productSQL As String = _
"SELECT Production.Product.Name FROM Production.Product " & _
"INNER JOIN Purchasing.ProductVendor " & _
"ON Production.Product.ProductID = " & _
"Purchasing.ProductVendor.ProductID " & _
"WHERE Purchasing.ProductVendor.VendorID = @VendorId"
Using awConnection As New SqlConnection(connectionString)
vendorCmd = New SqlCommand(vendorSQL, awConnection)
productCmd = New SqlCommand(productSQL, awConnection)
productCmd.Parameters.Add("@VendorId", SqlDbType.Int)
awConnection.Open()
Using vendorReader As SqlDataReader = vendorCmd.ExecuteReader()
While vendorReader.Read()
Console.WriteLine(vendorReader("Name"))
vendorID = CInt(vendorReader("VendorId"))
productCmd.Parameters("@VendorId").Value = vendorID
' The following line of code requires
' a MARS-enabled connection.
productReader = productCmd.ExecuteReader()
Using productReader
While productReader.Read()
Console.WriteLine(" " & CStr(productReader("Name")))
End While
End Using
End While
End Using
End Using
Console.WriteLine("Press any key to continue")
Console.ReadLine()
End Sub
Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
Return "..." & _
"MultipleActiveResultSets=True"
End Function
End Module
using System;
using System.Data;
using System.Data.SqlClient;
class Class1
{
static void Main()
{
// By default, MARS is disabled when connecting
// to a MARS-enabled host.
// It must be enabled in the connection string.
string connectionString = GetConnectionString();
int vendorID;
SqlDataReader productReader = null;
string vendorSQL =
"SELECT VendorId, Name FROM Purchasing.Vendor";
string productSQL =
"SELECT Production.Product.Name FROM Production.Product " +
"INNER JOIN Purchasing.ProductVendor " +
"ON Production.Product.ProductID = " +
"Purchasing.ProductVendor.ProductID " +
"WHERE Purchasing.ProductVendor.VendorID = @VendorId";
using (SqlConnection awConnection =
new SqlConnection(connectionString))
{
SqlCommand vendorCmd = new SqlCommand(vendorSQL, awConnection);
SqlCommand productCmd =
new SqlCommand(productSQL, awConnection);
productCmd.Parameters.Add("@VendorId", SqlDbType.Int);
awConnection.Open();
using (SqlDataReader vendorReader = vendorCmd.ExecuteReader())
{
while (vendorReader.Read())
{
Console.WriteLine(vendorReader["Name"]);
vendorID = (int)vendorReader["VendorId"];
productCmd.Parameters["@VendorId"].Value = vendorID;
// The following line of code requires
// a MARS-enabled connection.
productReader = productCmd.ExecuteReader();
using (productReader)
{
while (productReader.Read())
{
Console.WriteLine(" " +
productReader["Name"].ToString());
}
}
}
}
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
}
private static string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
return "..." +
"MultipleActiveResultSets=True";
}
}
Gegevens lezen en bijwerken met MARS
MET MARS kan een verbinding worden gebruikt voor zowel leesbewerkingen als DML-bewerkingen (Data Manipulat Language) met meer dan één in behandeling zijnde bewerking. Deze functie elimineert de noodzaak dat een toepassing te maken krijgt met verbindingsbezette fouten. Bovendien kan MARS het gebruik van cursors aan de serverzijde vervangen, die over het algemeen meer resources verbruiken. Ten slotte, omdat meerdere bewerkingen op één verbinding kunnen worden uitgevoerd, kunnen ze dezelfde transactiecontext delen, waardoor sp_getbindtoken en sp_bindsession opgeslagen procedures niet meer hoeven te worden gebruikt.
Opmerking
In de volgende consoletoepassing ziet u hoe u twee SqlDataReader objecten gebruikt met drie SqlCommand objecten en één SqlConnection object waarvoor MARS is ingeschakeld. Met het eerste opdrachtobject wordt een lijst opgehaald met leveranciers waarvan de waardering 5 is. Het tweede opdrachtobject gebruikt de leverancier-id van een SqlDataReader om de tweede SqlDataReader te laden met alle producten voor de specifieke leverancier. Elke productrecord wordt door de tweede SqlDataReaderbezocht. Er wordt een berekening uitgevoerd om te bepalen wat de nieuwe OnOrderQty moet zijn. Het derde opdrachtobject wordt vervolgens gebruikt om de tabel ProductVendor bij te werken met de nieuwe waarde. Dit hele proces vindt plaats binnen één transactie, die aan het einde wordt teruggedraaid.
Notitie
In het volgende voorbeeld wordt de voorbeelddatabase AdventureWorks gebruikt die is opgenomen in SQL Server. Bij het verbindingsreeks in de voorbeeldcode wordt ervan uitgegaan dat de database is geïnstalleerd en beschikbaar is op de lokale computer. Wijzig de verbindingsreeks indien nodig voor uw omgeving.
Option Strict On
Option Explicit On
Imports System
Imports System.Data
Imports System.Data.SqlClient
Module Module1
Sub Main()
' By default, MARS is disabled when connecting
' to a MARS-enabled host.
' It must be enabled in the connection string.
Dim connectionString As String = GetConnectionString()
Dim updateTx As SqlTransaction
Dim vendorCmd As SqlCommand
Dim prodVendCmd As SqlCommand
Dim updateCmd As SqlCommand
Dim prodVendReader As SqlDataReader
Dim vendorID As Integer
Dim productID As Integer
Dim minOrderQty As Integer
Dim maxOrderQty As Integer
Dim onOrderQty As Integer
Dim recordsUpdated As Integer
Dim totalRecordsUpdated As Integer
Dim vendorSQL As String = _
"SELECT VendorID, Name FROM Purchasing.Vendor " & _
"WHERE CreditRating = 5"
Dim prodVendSQL As String = _
"SELECT ProductID, MaxOrderQty, MinOrderQty, OnOrderQty " & _
"FROM Purchasing.ProductVendor " & _
"WHERE VendorID = @VendorID"
Dim updateSQL As String = _
"UPDATE Purchasing.ProductVendor " & _
"SET OnOrderQty = @OrderQty " & _
"WHERE ProductID = @ProductID AND VendorID = @VendorID"
Using awConnection As New SqlConnection(connectionString)
awConnection.Open()
updateTx = awConnection.BeginTransaction()
vendorCmd = New SqlCommand(vendorSQL, awConnection)
vendorCmd.Transaction = updateTx
prodVendCmd = New SqlCommand(prodVendSQL, awConnection)
prodVendCmd.Transaction = updateTx
prodVendCmd.Parameters.Add("@VendorId", SqlDbType.Int)
updateCmd = New SqlCommand(updateSQL, awConnection)
updateCmd.Transaction = updateTx
updateCmd.Parameters.Add("@OrderQty", SqlDbType.Int)
updateCmd.Parameters.Add("@ProductID", SqlDbType.Int)
updateCmd.Parameters.Add("@VendorID", SqlDbType.Int)
Using vendorReader As SqlDataReader = vendorCmd.ExecuteReader()
While vendorReader.Read()
Console.WriteLine(vendorReader("Name"))
vendorID = CInt(vendorReader("VendorID"))
prodVendCmd.Parameters("@VendorID").Value = vendorID
prodVendReader = prodVendCmd.ExecuteReader()
Using prodVendReader
While (prodVendReader.Read)
productID = CInt(prodVendReader("ProductID"))
If IsDBNull(prodVendReader("OnOrderQty")) Then
minOrderQty = CInt(prodVendReader("MinOrderQty"))
onOrderQty = minOrderQty
Else
maxOrderQty = CInt(prodVendReader("MaxOrderQty"))
onOrderQty = CInt(maxOrderQty / 2)
End If
updateCmd.Parameters("@OrderQty").Value = onOrderQty
updateCmd.Parameters("@ProductID").Value = productID
updateCmd.Parameters("@VendorID").Value = vendorID
recordsUpdated = updateCmd.ExecuteNonQuery()
totalRecordsUpdated += recordsUpdated
End While
End Using
End While
End Using
Console.WriteLine("Total Records Updated: " & _
CStr(totalRecordsUpdated))
updateTx.Rollback()
Console.WriteLine("Transaction Rolled Back")
End Using
Console.WriteLine("Press any key to continue")
Console.ReadLine()
End Sub
Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
Return "..." & _
"MultipleActiveResultSets=True"
End Function
End Module
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main()
{
// By default, MARS is disabled when connecting
// to a MARS-enabled host.
// It must be enabled in the connection string.
string connectionString = GetConnectionString();
SqlTransaction updateTx = null;
SqlCommand vendorCmd = null;
SqlCommand prodVendCmd = null;
SqlCommand updateCmd = null;
SqlDataReader prodVendReader = null;
int vendorID = 0;
int productID = 0;
int minOrderQty = 0;
int maxOrderQty = 0;
int onOrderQty = 0;
int recordsUpdated = 0;
int totalRecordsUpdated = 0;
string vendorSQL =
"SELECT VendorID, Name FROM Purchasing.Vendor " +
"WHERE CreditRating = 5";
string prodVendSQL =
"SELECT ProductID, MaxOrderQty, MinOrderQty, OnOrderQty " +
"FROM Purchasing.ProductVendor " +
"WHERE VendorID = @VendorID";
string updateSQL =
"UPDATE Purchasing.ProductVendor " +
"SET OnOrderQty = @OrderQty " +
"WHERE ProductID = @ProductID AND VendorID = @VendorID";
using (SqlConnection awConnection =
new SqlConnection(connectionString))
{
awConnection.Open();
updateTx = awConnection.BeginTransaction();
vendorCmd = new SqlCommand(vendorSQL, awConnection);
vendorCmd.Transaction = updateTx;
prodVendCmd = new SqlCommand(prodVendSQL, awConnection);
prodVendCmd.Transaction = updateTx;
prodVendCmd.Parameters.Add("@VendorId", SqlDbType.Int);
updateCmd = new SqlCommand(updateSQL, awConnection);
updateCmd.Transaction = updateTx;
updateCmd.Parameters.Add("@OrderQty", SqlDbType.Int);
updateCmd.Parameters.Add("@ProductID", SqlDbType.Int);
updateCmd.Parameters.Add("@VendorID", SqlDbType.Int);
using (SqlDataReader vendorReader = vendorCmd.ExecuteReader())
{
while (vendorReader.Read())
{
Console.WriteLine(vendorReader["Name"]);
vendorID = (int) vendorReader["VendorID"];
prodVendCmd.Parameters["@VendorID"].Value = vendorID;
prodVendReader = prodVendCmd.ExecuteReader();
using (prodVendReader)
{
while (prodVendReader.Read())
{
productID = (int) prodVendReader["ProductID"];
if (prodVendReader["OnOrderQty"] == DBNull.Value)
{
minOrderQty = (int) prodVendReader["MinOrderQty"];
onOrderQty = minOrderQty;
}
else
{
maxOrderQty = (int) prodVendReader["MaxOrderQty"];
onOrderQty = (int)(maxOrderQty / 2);
}
updateCmd.Parameters["@OrderQty"].Value = onOrderQty;
updateCmd.Parameters["@ProductID"].Value = productID;
updateCmd.Parameters["@VendorID"].Value = vendorID;
recordsUpdated = updateCmd.ExecuteNonQuery();
totalRecordsUpdated += recordsUpdated;
}
}
}
}
Console.WriteLine("Total Records Updated: " +
totalRecordsUpdated.ToString());
updateTx.Rollback();
Console.WriteLine("Transaction Rolled Back");
}
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
private static string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
return "..." +
"MultipleActiveResultSets=True";
}
}