SqlCommand.BeginExecuteReader Metódus
Definíció
Fontos
Egyes információk olyan, kiadás előtti termékekre vonatkoznak, amelyek a kiadásig még jelentősen módosulhatnak. A Microsoft nem vállal kifejezett vagy törvényi garanciát az itt megjelenő információért.
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, és lekéri egy vagy több eredményhalmazt a kiszolgálóról.
Túlterhelések
| Name | Description |
|---|---|
| BeginExecuteReader() |
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, és lekéri egy vagy több eredményhalmazt a kiszolgálóról. |
| BeginExecuteReader(CommandBehavior) |
A Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását kezdeményezi, amelyet az SqlCommand a CommandBehavior értékek egyikével ír le. |
| BeginExecuteReader(AsyncCallback, Object) |
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, és egy vagy több eredményhalmazt kér le a kiszolgálóról visszahívási eljárás és állapotinformációk alapján. |
| BeginExecuteReader(AsyncCallback, Object, CommandBehavior) |
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, az egyik |
BeginExecuteReader()
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, és lekéri egy vagy több eredményhalmazt a kiszolgálóról.
public:
IAsyncResult ^ BeginExecuteReader();
public IAsyncResult BeginExecuteReader();
member this.BeginExecuteReader : unit -> IAsyncResult
Public Function BeginExecuteReader () As IAsyncResult
Válaszok
Olyan IAsyncResult érték, amely az eredmények lekérdezésére vagy várakozására használható, vagy mindkettőre; erre az értékre a meghíváskor EndExecuteReader(IAsyncResult)is szükség van, amely egy olyan példányt SqlDataReader ad vissza, amely a visszaadott sorok lekérésére használható.
Kivételek
A SqlDbTypebináristól vagy a VarBinarytól eltérő függvényt használt a rendszer, amikor Value a beállítás értéke Stream. A streamelésről további információt az SqlClient streamelési támogatásában talál.
-vagy-
A SqlDbTypechar, NChar, NVarChar, VarChar vagy Xml kivételével más is használható volt a beállításnál ValueTextReader.
-vagy-
Az SqlDbTypeXml-fájltól eltérő érték lett használva a ValuebeállításkorXmlReader.
Bármilyen hiba, amely a parancsszöveg végrehajtása során történt.
-vagy-
Időtúllépés történt egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az "Aszinkron processing=true" név-érték pár nem szerepel a kapcsolati karakterlánc, amely meghatározza a SqlCommand kapcsolatát.
-vagy-
A SqlConnection streamelési művelet során bezárt vagy elvetett. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Hiba történt egy Stream, XmlReader vagy TextReader objektumban egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az Stream, XmlReader vagy TextReader objektum egy streamelési művelet során lett bezárva. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Példák
Az alábbi konzolalkalmazás elindítja az adatolvasó aszinkron beolvasásának folyamatát. Miközben az eredményekre vár, ez az egyszerű alkalmazás egy hurokban ül, és megvizsgálja a IsCompleted tulajdonság értékét. Amint a folyamat befejeződött, a kód lekéri a SqlDataReader kódot, és megjeleníti annak tartalmát.
using System.Data.SqlClient;
class Class1
{
static void Main()
{
// This is a simple example that demonstrates the usage of the
// BeginExecuteReader functionality
// The WAITFOR statement simply adds enough time to prove the
// asynchronous nature of the command.
string commandText =
"WAITFOR DELAY '00:00:03';" +
"SELECT LastName, FirstName FROM Person.Contact " +
"WHERE LastName LIKE 'M%'";
RunCommandAsynchronously(commandText, GetConnectionString());
Console.WriteLine("Press ENTER to continue.");
Console.ReadLine();
}
private static void RunCommandAsynchronously(
string commandText, string connectionString)
{
// Given command text and connection string, asynchronously execute
// the specified command against the connection. For this example,
// the code displays an indicator as it is working, verifying the
// asynchronous behavior.
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
SqlCommand command = new SqlCommand(commandText, connection);
connection.Open();
IAsyncResult result = command.BeginExecuteReader();
// Although it is not necessary, the following code
// displays a counter in the console window, indicating that
// the main thread is not blocked while awaiting the command
// results.
int count = 0;
while (!result.IsCompleted)
{
count += 1;
Console.WriteLine("Waiting ({0})", count);
// Wait for 1/10 second, so the counter
// does not consume all available resources
// on the main thread.
System.Threading.Thread.Sleep(100);
}
using (SqlDataReader reader = command.EndExecuteReader(result))
{
DisplayResults(reader);
}
}
catch (SqlException ex)
{
Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message);
}
catch (InvalidOperationException ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
catch (Exception ex)
{
// You might want to pass these errors
// back out to the caller.
Console.WriteLine("Error: {0}", ex.Message);
}
}
}
private static void DisplayResults(SqlDataReader reader)
{
// Display the data within the reader.
while (reader.Read())
{
// Display all the columns.
for (int i = 0; i < reader.FieldCount; i++)
Console.Write("{0} ", reader.GetValue(i));
Console.WriteLine();
}
}
private static string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you have not included "Asynchronous Processing=true" in the
// connection string, the command is not able
// to execute asynchronously.
return "Data Source=(local);Integrated Security=true;" +
"Initial Catalog=AdventureWorks; Asynchronous Processing=true";
}
}
Imports System.Data.SqlClient
Module Module1
Sub Main()
' This is a simple example that demonstrates the usage of the
' BeginExecuteReader functionality.
' The WAITFOR statement simply adds enough time to prove the
' asynchronous nature of the command.
Dim commandText As String = _
"WAITFOR DELAY '00:00:03';" & _
"SELECT LastName, FirstName FROM Person.Contact " & _
"WHERE LastName LIKE 'M%'"
RunCommandAsynchronously(commandText, GetConnectionString())
Console.WriteLine("Press ENTER to continue.")
Console.ReadLine()
End Sub
Private Sub RunCommandAsynchronously( _
ByVal commandText As String, ByVal connectionString As String)
' Given command text and connection string, asynchronously execute
' the specified command against the connection. For this example,
' the code displays an indicator as it is working, verifying the
' asynchronous behavior.
Using connection As New SqlConnection(connectionString)
Try
Dim command As New SqlCommand(commandText, connection)
connection.Open()
Dim result As IAsyncResult = command.BeginExecuteReader()
' Although it is not necessary, the following procedure
' displays a counter in the console window, indicating that
' the main thread is not blocked while awaiting the command
' results.
Dim count As Integer
While Not result.IsCompleted
count += 1
Console.WriteLine("Waiting ({0})", count)
' Wait for 1/10 second, so the counter
' does not consume all available resources
' on the main thread.
Threading.Thread.Sleep(100)
End While
' Once the IAsyncResult object signals that it is done
' waiting for results, you can retrieve the results.
Using reader As SqlDataReader = command.EndExecuteReader(result)
DisplayResults(reader)
End Using
Catch ex As SqlException
Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message)
Catch ex As InvalidOperationException
Console.WriteLine("Error: {0}", ex.Message)
Catch ex As Exception
' You might want to pass these errors
' back out to the caller.
Console.WriteLine("Error: {0}", ex.Message)
End Try
End Using
End Sub
Private Sub DisplayResults(ByVal reader As SqlDataReader)
' Display the data within the reader.
While reader.Read()
' Display all the columns.
For i As Integer = 0 To reader.FieldCount - 1
Console.Write("{0} ", reader.GetValue(i))
Next
Console.WriteLine()
End While
End Sub
Private Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
' If you have not included "Asynchronous Processing=true" in the
' connection string, the command is not able
' to execute asynchronously.
Return "Data Source=(local);Integrated Security=true;" & _
"Initial Catalog=AdventureWorks; Asynchronous Processing=true"
End Function
End Module
Megjegyzések
A BeginExecuteReader metódus elindítja a sorokat visszaadó Transact-SQL utasítás vagy tárolt eljárás aszinkron végrehajtásának folyamatát, hogy más feladatok párhuzamosan fussanak az utasítás végrehajtása közben. Ha az utasítás befejeződött, a fejlesztőknek meg kell hívniuk a metódust a EndExecuteReader művelet befejezéséhez és a SqlDataReader parancs által visszaadott adatok lekéréséhez. A BeginExecuteReader metódus azonnal visszatér, de amíg a kód nem hajtja végre a megfelelő EndExecuteReader metódushívást, nem hajthat végre más hívásokat, amelyek szinkron vagy aszinkron végrehajtást indítanak ugyanahhoz SqlCommand az objektumhoz. Ha a EndExecuteReader parancs végrehajtása előtt hívja meg az objektumot, az SqlCommand a végrehajtás befejezéséig blokkolódik.
Vegye figyelembe, hogy a parancs szövegét és paramétereit a rendszer szinkron módon küldi el a kiszolgálónak. Ha nagy parancsot vagy több paramétert küld, ez a módszer blokkolhatja az írások során. A parancs elküldése után a metódus azonnal visszatér, anélkül, hogy választ vár a kiszolgálótól – vagyis az olvasások aszinkronok. Bár a parancsvégrehajtás aszinkron, az értéklekérés továbbra is szinkron. Ez azt jelenti, hogy a hívás blokkolhatja Read , ha több adatra van szükség, és a mögöttes hálózat olvasási műveletblokkja.
Mivel ez a túlterhelés nem támogatja a visszahívási eljárást, a fejlesztőknek le kellkérdezniük, hogy a parancs befejeződött-e a metódus által IsCompleted visszaadott tulajdonság IAsyncResult használatávalBeginExecuteReader, vagy várniuk kell egy vagy több parancs befejezésére a AsyncWaitHandle visszaadott IAsyncResulttulajdonság használatával.
Ha ExecuteReader vagy BeginExecuteReader használatával fér hozzá az XML-adatokhoz, SQL Server minden 2033 karakternél hosszabb XML-eredményt ad vissza 2033 karakternél hosszabb sorokban, egyenként 2033 karakter hosszúságú sorokban. Ennek a viselkedésnek a elkerülése érdekében használja ExecuteXmlReader vagy BeginExecuteXmlReader olvassa el a FOR XML-lekérdezéseket.
Ez a metódus figyelmen kívül hagyja a tulajdonságot CommandTimeout .
Lásd még
- Az adatok összekapcsolása és lekérése az ADO-ban.NET
A .NET-keretrendszer Data Provider használata SQL Server - ADO.NET áttekintése
A következőre érvényes:
BeginExecuteReader(CommandBehavior)
A Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását kezdeményezi, amelyet az SqlCommand a CommandBehavior értékek egyikével ír le.
public:
IAsyncResult ^ BeginExecuteReader(System::Data::CommandBehavior behavior);
public IAsyncResult BeginExecuteReader(System.Data.CommandBehavior behavior);
member this.BeginExecuteReader : System.Data.CommandBehavior -> IAsyncResult
Public Function BeginExecuteReader (behavior As CommandBehavior) As IAsyncResult
Paraméterek
- behavior
- CommandBehavior
Az egyik CommandBehavior érték, amely az utasítás végrehajtásának és az adatok lekérésének lehetőségeit jelzi.
Válaszok
Egy IAsyncResult lekérdezéshez, az eredmények várakozásához vagy mindkettőhöz használható; ez az érték a lekérdezéskor EndExecuteReader(IAsyncResult)is szükséges, amely egy SqlDataReader olyan példányt ad vissza, amely a visszaadott sorok lekérésére használható.
Kivételek
A SqlDbTypebináristól vagy a VarBinarytól eltérő függvényt használt a rendszer, amikor Value a beállítás értéke Stream. A streamelésről további információt az SqlClient streamelési támogatásában talál.
-vagy-
A SqlDbTypechar, NChar, NVarChar, VarChar vagy Xml kivételével más is használható volt a beállításnál ValueTextReader.
-vagy-
Az SqlDbTypeXml-fájltól eltérő érték lett használva a ValuebeállításkorXmlReader.
Bármilyen hiba, amely a parancsszöveg végrehajtása során történt.
-vagy-
Időtúllépés történt egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az "Aszinkron processing=true" név-érték pár nem szerepel a kapcsolati karakterlánc, amely meghatározza a SqlCommand kapcsolatát.
-vagy-
A SqlConnection streamelési művelet során bezárt vagy elvetett. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Hiba történt egy Stream, XmlReader vagy TextReader objektumban egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az Stream, XmlReader vagy TextReader objektum egy streamelési művelet során lett bezárva. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Példák
Az alábbi konzolalkalmazás elindítja az adatolvasó aszinkron beolvasásának folyamatát. Miközben az eredményekre vár, ez az egyszerű alkalmazás egy hurokban ül, és megvizsgálja a IsCompleted tulajdonság értékét. A folyamat befejezése után a kód lekéri a SqlDataReader kódot, és megjeleníti annak tartalmát.
Ez a CommandBehavior.CloseConnection példa a viselkedési paraméterben szereplő értékeket is CommandBehavior.SingleRow átadja, így a visszaadott SqlDataReader kapcsolat bezárul, és egyetlen sor eredményére optimalizálható.
using System.Data.SqlClient;
class Class1
{
static void Main()
{
// This example is not terribly useful, but it proves a point.
// The WAITFOR statement simply adds enough time to prove the
// asynchronous nature of the command.
string commandText = "WAITFOR DELAY '00:00:03';" +
"SELECT ProductID, Name FROM Production.Product WHERE ListPrice < 100";
RunCommandAsynchronously(commandText, GetConnectionString());
Console.WriteLine("Press ENTER to continue.");
Console.ReadLine();
}
private static void RunCommandAsynchronously(
string commandText, string connectionString)
{
// Given command text and connection string, asynchronously execute
// the specified command against the connection. For this example,
// the code displays an indicator as it is working, verifying the
// asynchronous behavior.
try
{
// The code does not need to handle closing the connection explicitly--
// the use of the CommandBehavior.CloseConnection option takes care
// of that for you.
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(commandText, connection);
connection.Open();
IAsyncResult result = command.BeginExecuteReader(
CommandBehavior.CloseConnection);
// Although it is not necessary, the following code
// displays a counter in the console window, indicating that
// the main thread is not blocked while awaiting the command
// results.
int count = 0;
while (!result.IsCompleted)
{
Console.WriteLine("Waiting ({0})", count++);
// Wait for 1/10 second, so the counter
// does not consume all available resources
// on the main thread.
System.Threading.Thread.Sleep(100);
}
using (SqlDataReader reader = command.EndExecuteReader(result))
{
DisplayResults(reader);
}
}
catch (SqlException ex)
{
Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message);
}
catch (InvalidOperationException ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
catch (Exception ex)
{
// You might want to pass these errors
// back out to the caller.
Console.WriteLine("Error: {0}", ex.Message);
}
}
private static void DisplayResults(SqlDataReader reader)
{
// Display the data within the reader.
while (reader.Read())
{
// Display all the columns.
for (int i = 0; i < reader.FieldCount; i++)
{
Console.Write("{0}\t", reader.GetValue(i));
}
Console.WriteLine();
}
}
private static string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you have not included "Asynchronous Processing=true" in the
// connection string, the command is not able
// to execute asynchronously.
return "Data Source=(local);Integrated Security=true;" +
"Initial Catalog=AdventureWorks; Asynchronous Processing=true";
}
}
Imports System.Data.SqlClient
Module Module1
Sub Main()
' This example is not terribly useful, but it proves a point.
' The WAITFOR statement simply adds enough time to prove the
' asynchronous nature of the command.
Dim commandText As String = _
"WAITFOR DELAY '00:00:03';" & _
"SELECT ProductID, Name FROM Production.Product WHERE ListPrice < 100"
RunCommandAsynchronously(commandText, GetConnectionString())
Console.WriteLine("Press ENTER to continue.")
Console.ReadLine()
End Sub
Private Sub RunCommandAsynchronously( _
ByVal commandText As String, ByVal connectionString As String)
' Given command text and connection string, asynchronously execute
' the specified command against the connection. For this example,
' the code displays an indicator as it is working, verifying the
' asynchronous behavior.
Try
' The code does not need to handle closing the connection explicitly--
' the use of the CommandBehavior.CloseConnection option takes care
' of that for you.
Dim connection As New SqlConnection(connectionString)
Dim command As New SqlCommand(commandText, connection)
connection.Open()
Dim result As IAsyncResult = _
command.BeginExecuteReader(CommandBehavior.CloseConnection)
' Although it is not necessary, the following code
' displays a counter in the console window, indicating that
' the main thread is not blocked while awaiting the command
' results.
Dim count As Integer = 0
While Not result.IsCompleted
count += 1
Console.WriteLine("Waiting ({0})", count)
' Wait for 1/10 second, so the counter
' does not consume all available resources
' on the main thread.
Threading.Thread.Sleep(100)
End While
' The "using" statement closes the SqlDataReader when it is
' done executing.
Using reader As SqlDataReader = command.EndExecuteReader(result)
DisplayResults(reader)
End Using
Catch ex As SqlException
Console.WriteLine("Error ({0}): {1}", ex.Number, ex.Message)
Catch ex As InvalidOperationException
Console.WriteLine("Error: {0}", ex.Message)
Catch ex As Exception
' You might want to pass these errors
' back out to the caller.
Console.WriteLine("Error: {0}", ex.Message)
End Try
End Sub
Private Sub DisplayResults(ByVal reader As SqlDataReader)
' Display the data within the reader.
While reader.Read()
' Display all the columns.
For i As Integer = 0 To reader.FieldCount - 1
Console.Write("{0} ", reader.GetValue(i))
Next
Console.WriteLine()
End While
End Sub
Private Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
' If you have not included "Asynchronous Processing=true" in the
' connection string, the command is not able
' to execute asynchronously.
Return "Data Source=(local);Integrated Security=true;" & _
"Initial Catalog=AdventureWorks; Asynchronous Processing=true"
End Function
End Module
Megjegyzések
A BeginExecuteReader metódus elindítja a sorokat visszaadó Transact-SQL utasítás vagy tárolt eljárás aszinkron végrehajtásának folyamatát, hogy más feladatok párhuzamosan fussanak az utasítás végrehajtása közben. Ha az utasítás befejeződött, a fejlesztőknek meg kell hívniuk a metódust a EndExecuteReader művelet befejezéséhez és a SqlDataReader parancs által visszaadott adatok lekéréséhez. A BeginExecuteReader metódus azonnal visszatér, de amíg a kód nem hajtja végre a megfelelő EndExecuteReader metódushívást, nem hajthat végre más hívásokat, amelyek szinkron vagy aszinkron végrehajtást indítanak ugyanahhoz SqlCommand az objektumhoz. Ha a EndExecuteReader parancs végrehajtása előtt hívja meg az objektumot, az SqlCommand a végrehajtás befejezéséig blokkolódik.
A behavior paraméter lehetővé teszi a parancs és a kapcsolat viselkedését vezérlő beállítások megadását. Ezek az értékek kombinálhatók (a programozási nyelv operátorának OR használatával); a fejlesztők általában arra használják az CommandBehavior.CloseConnection értéket, hogy a kapcsolat a futtatókörnyezet SqlDataReader által bezárt állapotban legyen.
Vegye figyelembe, hogy a parancs szövegét és paramétereit a rendszer szinkron módon küldi el a kiszolgálónak. Ha nagy parancsot vagy több paramétert küld, ez a módszer blokkolhatja az írások során. A parancs elküldése után a metódus azonnal visszatér, anélkül, hogy választ vár a kiszolgálótól – vagyis az olvasások aszinkronok. Bár a parancsvégrehajtás aszinkron, az értéklekérés továbbra is szinkron. Ez azt jelenti, hogy a hívás blokkolhatja Read , ha több adatra van szükség, és a mögöttes hálózat olvasási műveletblokkja.
Mivel ez a túlterhelés nem támogatja a visszahívási eljárást, a fejlesztőknek le kellkérdezniük, hogy a parancs befejeződött-e a metódus által IsCompleted visszaadott tulajdonság IAsyncResult használatávalBeginExecuteNonQuery, vagy várniuk kell egy vagy több parancs befejezésére a AsyncWaitHandle visszaadott IAsyncResulttulajdonság használatával.
Ha ExecuteReader vagy BeginExecuteReader használatával fér hozzá az XML-adatokhoz, SQL Server 2033 karakternél hosszabb XML-eredményeket ad vissza több, egyenként 2033 karakter hosszúságú sorban. Ennek a viselkedésnek a elkerülése érdekében használja ExecuteXmlReader vagy BeginExecuteXmlReader olvassa el a FOR XML-lekérdezéseket.
Ez a metódus figyelmen kívül hagyja a tulajdonságot CommandTimeout .
Lásd még
- Az adatok összekapcsolása és lekérése az ADO-ban.NET
A .NET-keretrendszer Data Provider használata SQL Server - ADO.NET áttekintése
A következőre érvényes:
BeginExecuteReader(AsyncCallback, Object)
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, és egy vagy több eredményhalmazt kér le a kiszolgálóról visszahívási eljárás és állapotinformációk alapján.
public:
IAsyncResult ^ BeginExecuteReader(AsyncCallback ^ callback, System::Object ^ stateObject);
public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObject);
member this.BeginExecuteReader : AsyncCallback * obj -> IAsyncResult
Public Function BeginExecuteReader (callback As AsyncCallback, stateObject As Object) As IAsyncResult
Paraméterek
- callback
- AsyncCallback
Egy AsyncCallback meghatalmazott, amelyet a parancs végrehajtása után hív meg a rendszer. Adja át a null (Nothing a Microsoft Visual Basic)-ban, hogy jelezze, nincs szükség visszahívásra.
- stateObject
- Object
A visszahívási eljárásnak átadott, felhasználó által definiált állapotobjektum. Kérje le ezt az objektumot a visszahívási eljárásból a AsyncState tulajdonság használatával.
Válaszok
Egy IAsyncResult lekérdezéshez, az eredmények várakozásához vagy mindkettőhöz használható; ez az érték a lekérdezéskor EndExecuteReader(IAsyncResult)is szükséges, amely egy SqlDataReader olyan példányt ad vissza, amely a visszaadott sorok lekérésére használható.
Kivételek
A SqlDbTypebináristól vagy a VarBinarytól eltérő függvényt használt a rendszer, amikor Value a beállítás értéke Stream. A streamelésről további információt az SqlClient streamelési támogatásában talál.
-vagy-
A SqlDbTypechar, NChar, NVarChar, VarChar vagy Xml kivételével más is használható volt a beállításnál ValueTextReader.
-vagy-
Az SqlDbTypeXml-fájltól eltérő érték lett használva a ValuebeállításkorXmlReader.
Bármilyen hiba, amely a parancsszöveg végrehajtása során történt.
-vagy-
Időtúllépés történt egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az "Aszinkron processing=true" név-érték pár nem szerepel a kapcsolati karakterlánc, amely meghatározza a SqlCommand kapcsolatát.
-vagy-
A SqlConnection streamelési művelet során bezárt vagy elvetett. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Hiba történt egy Stream, XmlReader vagy TextReader objektumban egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az Stream, XmlReader vagy TextReader objektum egy streamelési művelet során lett bezárva. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Példák
A következő Windows-alkalmazás bemutatja a BeginExecuteReader metódus használatát, és végrehajt egy Transact-SQL utasítást, amely néhány másodperces késleltetést tartalmaz (hosszú ideig futó parancsot emulál). Mivel a minta aszinkron módon hajtja végre a parancsot, az űrlap válaszkész marad, miközben várja az eredményeket. Ez a példa paraméterként adja át a végrehajtó SqlCommand objektumot; így egyszerűen lekérheti az objektumot a stateObject visszahívási eljáráson belül, hogy a kód meghívhassa a SqlCommand kezdeti hívásnak megfelelő metódustEndExecuteReader.BeginExecuteReader
Ez a példa számos fontos technikát mutat be. Ez magában foglalja egy metódus meghívását, amely egy külön szálból használja az űrlapot. Ez a példa azt is bemutatja, hogyan kell megakadályoznia, hogy a felhasználók egyszerre többször hajtsanak végre parancsokat, és hogyan kell meggyőződnie arról, hogy az űrlap nem záródik be a visszahívási eljárás meghívása előtt.
A példa beállításához hozzon létre egy új Windows-alkalmazást. Helyezzen egy vezérlőt Button , egy vezérlőt DataGridView és egy vezérlőelemet Label az űrlapra (elfogadva az egyes vezérlők alapértelmezett nevét). Adja hozzá az alábbi kódot az űrlap osztályához, és módosítsa a környezethez szükséges kapcsolati karakterlánc.
using System.Data.SqlClient;
namespace Microsoft.AdoDotNet.CodeSamples
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Hook up the form's Load event handler (you can double-click on
// the form's design surface in Visual Studio), and then add
// this code to the form's class:
// You need this delegate in order to fill the grid from
// a thread other than the form's thread. See the HandleCallback
// procedure for more information.
private delegate void FillGridDelegate(SqlDataReader reader);
// You need this delegate to update the status bar.
private delegate void DisplayStatusDelegate(string Text);
// This flag ensures that the user does not attempt
// to restart the command or close the form while the
// asynchronous command is executing.
private bool isExecuting = false;
// Because the overloaded version of BeginExecuteReader
// demonstrated here does not allow you to have the connection
// closed automatically, this example maintains the
// connection object externally, so that it is available for closing.
private SqlConnection connection = null;
private void DisplayStatus(string Text)
{
this.label1.Text = Text;
}
private void FillGrid(SqlDataReader reader)
{
try
{
DataTable table = new DataTable();
table.Load(reader);
this.dataGridView1.DataSource = table;
DisplayStatus("Ready");
}
catch (Exception ex)
{
// Because you are guaranteed this procedure
// is running from within the form's thread,
// it can directly interact with members of the form.
DisplayStatus(string.Format("Ready (last attempt failed: {0})",
ex.Message));
}
finally
{
// Do not forget to close the connection, as well.
if (reader != null)
{
reader.Close();
}
if (connection != null)
{
connection.Close();
}
}
}
private void HandleCallback(IAsyncResult result)
{
try
{
// Retrieve the original command object, passed
// to this procedure in the AsyncState property
// of the IAsyncResult parameter.
SqlCommand command = (SqlCommand)result.AsyncState;
SqlDataReader reader = command.EndExecuteReader(result);
// You may not interact with the form and its contents
// from a different thread, and this callback procedure
// is all but guaranteed to be running from a different thread
// than the form. Therefore you cannot simply call code that
// fills the grid, like this:
// FillGrid(reader);
// Instead, you must call the procedure from the form's thread.
// One simple way to accomplish this is to call the Invoke
// method of the form, which calls the delegate you supply
// from the form's thread.
FillGridDelegate del = new FillGridDelegate(FillGrid);
this.Invoke(del, reader);
// Do not close the reader here, because it is being used in
// a separate thread. Instead, have the procedure you have
// called close the reader once it is done with it.
}
catch (Exception ex)
{
// Because you are now running code in a separate thread,
// if you do not handle the exception here, none of your other
// code catches the exception. Because there is none of
// your code on the call stack in this thread, there is nothing
// higher up the stack to catch the exception if you do not
// handle it here. You can either log the exception or
// invoke a delegate (as in the non-error case in this
// example) to display the error on the form. In no case
// can you simply display the error without executing a delegate
// as in the try block here.
// You can create the delegate instance as you
// invoke it, like this:
this.Invoke(new DisplayStatusDelegate(DisplayStatus),
"Error: " + ex.Message);
}
finally
{
isExecuting = false;
}
}
private string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you do not include the Asynchronous Processing=true name/value pair,
// you wo not be able to execute the command asynchronously.
return "Data Source=(local);Integrated Security=true;" +
"Initial Catalog=AdventureWorks; Asynchronous Processing=true";
}
private void button1_Click(object sender, System.EventArgs e)
{
if (isExecuting)
{
MessageBox.Show(this,
"Already executing. Please wait until the current query " +
"has completed.");
}
else
{
SqlCommand command = null;
try
{
DisplayStatus("Connecting...");
connection = new SqlConnection(GetConnectionString());
// To emulate a long-running query, wait for
// a few seconds before retrieving the real data.
command = new SqlCommand("WAITFOR DELAY '0:0:5';" +
"SELECT ProductID, Name, ListPrice, Weight FROM Production.Product",
connection);
connection.Open();
DisplayStatus("Executing...");
isExecuting = true;
// Although it is not required that you pass the
// SqlCommand object as the second parameter in the
// BeginExecuteReader call, doing so makes it easier
// to call EndExecuteReader in the callback procedure.
AsyncCallback callback = new AsyncCallback(HandleCallback);
command.BeginExecuteReader(callback, command);
}
catch (Exception ex)
{
DisplayStatus("Error: " + ex.Message);
if (connection != null)
{
connection.Close();
}
}
}
}
private void Form1_Load(object sender, System.EventArgs e)
{
this.button1.Click += new System.EventHandler(this.button1_Click);
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (isExecuting)
{
MessageBox.Show(this, "Cannot close the form until " +
"the pending asynchronous command has completed. Please wait...");
e.Cancel = true;
}
}
}
}
Imports System.Data.SqlClient
Public Class Form1
' Add this code to the form's class:
' You need this delegate in order to fill the grid from
' a thread other than the form's thread. See the HandleCallback
' procedure for more information.
Private Delegate Sub FillGridDelegate(ByVal reader As SqlDataReader)
' You need this delegate to update the status bar.
Private Delegate Sub DisplayStatusDelegate(ByVal Text As String)
' This flag ensures that the user does not attempt
' to restart the command or close the form while the
' asynchronous command is executing.
Private isExecuting As Boolean
' Because the overloaded version of BeginExecuteReader
' demonstrated here does not allow you to have the connection
' closed automatically, this example maintains the
' connection object externally, so that it is available for closing.
Private connection As SqlConnection
Private Sub DisplayStatus(ByVal Text As String)
Me.Label1.Text = Text
End Sub
Private Sub FillGrid(ByVal reader As SqlDataReader)
Try
Dim table As New DataTable
table.Load(reader)
Me.DataGridView1.DataSource = table
DisplayStatus("Ready")
Catch ex As Exception
' Because you are guaranteed this procedure
' is running from within the form's thread,
' it can directly interact with members of the form.
DisplayStatus(String.Format("Ready (last attempt failed: {0})", ex.Message))
Finally
' Do not forget to close the connection, as well.
If Not reader Is Nothing Then
reader.Close()
End If
If Not connection Is Nothing Then
connection.Close()
End If
End Try
End Sub
Private Sub HandleCallback(ByVal result As IAsyncResult)
Try
' Retrieve the original command object, passed
' to this procedure in the AsyncState property
' of the IAsyncResult parameter.
Dim command As SqlCommand = CType(result.AsyncState, SqlCommand)
Dim reader As SqlDataReader = command.EndExecuteReader(result)
' You may not interact with the form and its contents
' from a different thread, and this callback procedure
' is all but guaranteed to be running from a different thread
' than the form. Therefore you cannot simply call code that
' fills the grid, like this:
' FillGrid(reader)
' Instead, you must call the procedure from the form's thread.
' One simple way to accomplish this is to call the Invoke
' method of the form, which calls the delegate you supply
' from the form's thread.
Dim del As New FillGridDelegate(AddressOf FillGrid)
Me.Invoke(del, reader)
' Do not close the reader here, because it is being used in
' a separate thread. Instead, have the procedure you have
' called close the reader once it is done with it.
Catch ex As Exception
' Because you are now running code in a separate thread,
' if you do not handle the exception here, none of your other
' code catches the exception. Because there is none of
' your code on the call stack in this thread, there is nothing
' higher up the stack to catch the exception if you do not
' handle it here. You can either log the exception or
' invoke a delegate (as in the non-error case in this
' example) to display the error on the form. In no case
' can you simply display the error without executing a delegate
' as in the Try block here.
' You can create the delegate instance as you
' invoke it, like this:
Me.Invoke(New DisplayStatusDelegate(AddressOf DisplayStatus), _
"Error: " & ex.Message)
Finally
isExecuting = False
End Try
End Sub
Private Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
' If you do not include the Asynchronous Processing=true name/value pair,
' you wo not be able to execute the command asynchronously.
Return "Data Source=(local);Integrated Security=true;" & _
"Initial Catalog=AdventureWorks; Asynchronous Processing=true"
End Function
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
If isExecuting Then
MessageBox.Show(Me, _
"Already executing. Please wait until the current query " & _
"has completed.")
Else
Dim command As SqlCommand
Try
DisplayStatus("Connecting...")
connection = New SqlConnection(GetConnectionString())
' To emulate a long-running query, wait for
' a few seconds before retrieving the real data.
command = New SqlCommand( _
"WAITFOR DELAY '0:0:5';" & _
"SELECT ProductID, Name, ListPrice, Weight FROM Production.Product", _
connection)
connection.Open()
DisplayStatus("Executing...")
isExecuting = True
' Although it is not required that you pass the
' SqlCommand object as the second parameter in the
' BeginExecuteReader call, doing so makes it easier
' to call EndExecuteReader in the callback procedure.
Dim callback As New AsyncCallback(AddressOf HandleCallback)
command.BeginExecuteReader(callback, command)
Catch ex As Exception
DisplayStatus("Error: " & ex.Message)
If connection IsNot Nothing Then
connection.Close()
End If
End Try
End If
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, _
ByVal e As System.Windows.Forms.FormClosingEventArgs) _
Handles Me.FormClosing
If isExecuting Then
MessageBox.Show(Me, "Cannot close the form until " & _
"the pending asynchronous command has completed. Please wait...")
e.Cancel = True
End If
End Sub
End Class
Megjegyzések
A BeginExecuteReader metódus elindítja a sorokat visszaadó Transact-SQL utasítás vagy tárolt eljárás aszinkron végrehajtásának folyamatát, hogy más feladatok párhuzamosan fussanak az utasítás végrehajtása közben. Ha az utasítás befejeződött, a fejlesztőknek meg kell hívniuk a metódust a EndExecuteReader művelet befejezéséhez és a SqlDataReader parancs által visszaadott adatok lekéréséhez. A BeginExecuteReader metódus azonnal visszatér, de amíg a kód nem hajtja végre a megfelelő EndExecuteReader metódushívást, nem hajthat végre más hívásokat, amelyek szinkron vagy aszinkron végrehajtást indítanak ugyanahhoz SqlCommand az objektumhoz. Ha a EndExecuteReader parancs végrehajtása előtt meghívja az objektumot, a SqlCommand végrehajtás befejezéséig blokkolva lesz.
A callback paraméter lehetővé teszi egy meghatalmazott megadását AsyncCallback , amelyet az utasítás befejezésekor hív meg. A metódust meghívhatja ezen a EndExecuteReader delegálási eljáráson belül, vagy az alkalmazás bármely más helyről. Emellett a paraméter bármely stateObject objektumát átadhatja, a visszahívási eljárás pedig lekérheti ezeket az adatokat a AsyncState tulajdonság használatával.
Vegye figyelembe, hogy a parancs szövegét és paramétereit a rendszer szinkron módon küldi el a kiszolgálónak. Ha nagy parancsot vagy több paramétert küld, ez a módszer blokkolhatja az írások során. A parancs elküldése után a metódus azonnal visszatér, anélkül, hogy választ vár a kiszolgálótól – vagyis az olvasások aszinkronok. Bár a parancsvégrehajtás aszinkron, az értéklekérés továbbra is szinkron. Ez azt jelenti, hogy a hívás blokkolhatja Read , ha több adatra van szükség, és a mögöttes hálózat olvasási műveletblokkja.
Mivel a visszahívási eljárás a Microsoft .NET futtatókörnyezet által biztosított háttérszálból történik, nagyon fontos, hogy szigorú megközelítést alkalmazzon a szálközi interakciók alkalmazáson belüli kezelésére. Például nem használhatja az űrlap tartalmát a visszahívási eljáráson belül; ha frissítenie kell az űrlapot, a munka elvégzéséhez vissza kell váltania az űrlap szálára. A jelen témakörben szereplő példa ezt a viselkedést mutatja be.
A művelet végrehajtása során előforduló összes hiba kivételként jelenik meg a visszahívási eljárásban. A kivételt a visszahívási eljárásban kell kezelnie, nem a fő alkalmazásban. A visszahívási eljárás kivételeinek kezelésével kapcsolatos további információkért tekintse meg a jelen témakörben található példát.
Ha ExecuteReader vagy BeginExecuteReader használatával fér hozzá az XML-adatokhoz, SQL Server 2033 karakternél hosszabb XML-eredményeket ad vissza több, egyenként 2033 karakter hosszúságú sorban. Ennek a viselkedésnek a elkerülése érdekében használja ExecuteXmlReader vagy BeginExecuteXmlReader olvassa el a FOR XML-lekérdezéseket.
Ez a metódus figyelmen kívül hagyja a tulajdonságot CommandTimeout .
Lásd még
- Az adatok összekapcsolása és lekérése az ADO-ban.NET
A .NET-keretrendszer Data Provider használata SQL Server - ADO.NET áttekintése
A következőre érvényes:
BeginExecuteReader(AsyncCallback, Object, CommandBehavior)
Elindítja a Transact-SQL utasítás vagy a tárolt eljárás aszinkron végrehajtását, amelyet ez a SqlCommand ír le, az egyik CommandBehavior érték használatával, és lekér egy vagy több eredményhalmazt a kiszolgálóról visszahívási eljárás és állapotadatok alapján.
public:
IAsyncResult ^ BeginExecuteReader(AsyncCallback ^ callback, System::Object ^ stateObject, System::Data::CommandBehavior behavior);
public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObject, System.Data.CommandBehavior behavior);
member this.BeginExecuteReader : AsyncCallback * obj * System.Data.CommandBehavior -> IAsyncResult
Public Function BeginExecuteReader (callback As AsyncCallback, stateObject As Object, behavior As CommandBehavior) As IAsyncResult
Paraméterek
- callback
- AsyncCallback
Egy AsyncCallback meghatalmazott, amelyet a parancs végrehajtása után hív meg a rendszer. Adja át a null (Nothing a Microsoft Visual Basic)-ban, hogy jelezze, nincs szükség visszahívásra.
- stateObject
- Object
A visszahívási eljárásnak átadott, felhasználó által definiált állapotobjektum. Kérje le ezt az objektumot a visszahívási eljárásból a AsyncState tulajdonság használatával.
- behavior
- CommandBehavior
Az egyik CommandBehavior érték, amely az utasítás végrehajtásának és az adatok lekérésének lehetőségeit jelzi.
Válaszok
Olyan IAsyncResult érték, amely az eredmények lekérdezésére vagy várakozására használható, vagy mindkettőre; erre az értékre a meghíváskor EndExecuteReader(IAsyncResult)is szükség van, amely egy olyan példányt SqlDataReader ad vissza, amely a visszaadott sorok lekérésére használható.
Kivételek
A SqlDbTypebináristól vagy a VarBinarytól eltérő függvényt használt a rendszer, amikor Value a beállítás értéke Stream. A streamelésről további információt az SqlClient streamelési támogatásában talál.
-vagy-
A SqlDbTypechar, NChar, NVarChar, VarChar vagy Xml kivételével más is használható volt a beállításnál ValueTextReader.
-vagy-
Az SqlDbTypeXml-fájltól eltérő érték lett használva a ValuebeállításkorXmlReader.
Bármilyen hiba, amely a parancsszöveg végrehajtása során történt.
-vagy-
Időtúllépés történt egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az "Aszinkron processing=true" név-érték pár nem szerepel a kapcsolati karakterlánc, amely meghatározza a SqlCommand kapcsolatát.
-vagy-
A SqlConnection streamelési művelet során bezárt vagy elvetett. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Hiba történt egy Stream, XmlReader vagy TextReader objektumban egy streamelési művelet során. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Az Stream, XmlReader vagy TextReader objektum egy streamelési művelet során lett bezárva. A streamelésről további információt az SqlClient streamelési támogatásában talál.
Példák
A következő Windows-alkalmazás bemutatja a BeginExecuteReader metódus használatát, és végrehajt egy Transact-SQL utasítást, amely néhány másodperces késleltetést tartalmaz (hosszú ideig futó parancsot emulál). Mivel a minta aszinkron módon hajtja végre a parancsot, az űrlap válaszkész marad, miközben várja az eredményeket. Ez a példa paraméterként adja át a végrehajtó SqlCommand objektumot; így egyszerűen lekérheti az objektumot a stateObject visszahívási eljáráson belül, hogy a kód meghívhassa a SqlCommand kezdeti hívásnak megfelelő metódustEndExecuteReader.BeginExecuteReader
Ez a példa számos fontos technikát mutat be. Ez magában foglalja egy metódus meghívását, amely egy külön szálból használja az űrlapot. Ez a példa azt is bemutatja, hogyan kell megakadályoznia, hogy a felhasználók egyszerre többször hajtsanak végre parancsokat, és hogyan kell meggyőződnie arról, hogy az űrlap nem záródik be a visszahívási eljárás meghívása előtt.
A példa beállításához hozzon létre egy új Windows-alkalmazást. Helyezzen egy vezérlőt Button , egy vezérlőt DataGridView és egy vezérlőelemet Label az űrlapra (elfogadva az egyes vezérlők alapértelmezett nevét). Adja hozzá az alábbi kódot az űrlap osztályához, és módosítsa a környezethez szükséges kapcsolati karakterlánc.
Ez a példa átadja a CommandBehavior.CloseConnectionbehavior paraméter értékét, így a visszaadott SqlDataReader érték automatikusan bezárja a kapcsolatot.
using System.Data.SqlClient;
namespace Microsoft.AdoDotNet.CodeSamples
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Hook up the form's Load event handler (you can double-click on
// the form's design surface in Visual Studio), and then add
// this code to the form's class:
// You need this delegate in order to fill the grid from
// a thread other than the form's thread. See the HandleCallback
// procedure for more information.
private delegate void FillGridDelegate(SqlDataReader reader);
// You need this delegate to update the status bar.
private delegate void DisplayStatusDelegate(string Text);
// This flag ensures that the user does not attempt
// to restart the command or close the form while the
// asynchronous command is executing.
private bool isExecuting;
private void DisplayStatus(string Text)
{
this.label1.Text = Text;
}
private void FillGrid(SqlDataReader reader)
{
try
{
DataTable table = new DataTable();
table.Load(reader);
this.dataGridView1.DataSource = table;
DisplayStatus("Ready");
}
catch (Exception ex)
{
// Because you are guaranteed this procedure
// is running from within the form's thread,
// it can directly interact with members of the form.
DisplayStatus(string.Format("Ready (last attempt failed: {0})",
ex.Message));
}
finally
{
// Closing the reader also closes the connection,
// because this reader was created using the
// CommandBehavior.CloseConnection value.
if (reader != null)
{
reader.Close();
}
}
}
private void HandleCallback(IAsyncResult result)
{
try
{
// Retrieve the original command object, passed
// to this procedure in the AsyncState property
// of the IAsyncResult parameter.
SqlCommand command = (SqlCommand)result.AsyncState;
SqlDataReader reader = command.EndExecuteReader(result);
// You may not interact with the form and its contents
// from a different thread, and this callback procedure
// is all but guaranteed to be running from a different thread
// than the form. Therefore you cannot simply call code that
// fills the grid, like this:
// FillGrid(reader);
// Instead, you must call the procedure from the form's thread.
// One simple way to accomplish this is to call the Invoke
// method of the form, which calls the delegate you supply
// from the form's thread.
FillGridDelegate del = new FillGridDelegate(FillGrid);
this.Invoke(del, reader);
// Do not close the reader here, because it is being used in
// a separate thread. Instead, have the procedure you have
// called close the reader once it is done with it.
}
catch (Exception ex)
{
// Because you are now running code in a separate thread,
// if you do not handle the exception here, none of your other
// code catches the exception. Because there is none of
// your code on the call stack in this thread, there is nothing
// higher up the stack to catch the exception if you do not
// handle it here. You can either log the exception or
// invoke a delegate (as in the non-error case in this
// example) to display the error on the form. In no case
// can you simply display the error without executing a delegate
// as in the try block here.
// You can create the delegate instance as you
// invoke it, like this:
this.Invoke(new DisplayStatusDelegate(DisplayStatus), "Error: " +
ex.Message);
}
finally
{
isExecuting = false;
}
}
private string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
// If you do not include the Asynchronous Processing=true name/value pair,
// you wo not be able to execute the command asynchronously.
return "Data Source=(local);Integrated Security=true;" +
"Initial Catalog=AdventureWorks; Asynchronous Processing=true";
}
private void button1_Click(object sender, System.EventArgs e)
{
if (isExecuting)
{
MessageBox.Show(this,
"Already executing. Please wait until the current query " +
"has completed.");
}
else
{
SqlCommand command = null;
SqlConnection connection = null;
try
{
DisplayStatus("Connecting...");
connection = new SqlConnection(GetConnectionString());
// To emulate a long-running query, wait for
// a few seconds before retrieving the real data.
command = new SqlCommand("WAITFOR DELAY '0:0:5';" +
"SELECT ProductID, Name, ListPrice, Weight FROM Production.Product",
connection);
connection.Open();
DisplayStatus("Executing...");
isExecuting = true;
// Although it is not required that you pass the
// SqlCommand object as the second parameter in the
// BeginExecuteReader call, doing so makes it easier
// to call EndExecuteReader in the callback procedure.
AsyncCallback callback = new AsyncCallback(HandleCallback);
command.BeginExecuteReader(callback, command,
CommandBehavior.CloseConnection);
}
catch (Exception ex)
{
DisplayStatus("Error: " + ex.Message);
if (connection != null)
{
connection.Close();
}
}
}
}
private void Form1_Load(object sender, System.EventArgs e)
{
this.button1.Click += new System.EventHandler(this.button1_Click);
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (isExecuting)
{
MessageBox.Show(this, "Cannot close the form until " +
"the pending asynchronous command has completed. Please wait...");
e.Cancel = true;
}
}
}
}
Imports System.Data.SqlClient
Public Class Form1
' Add this code to the form's class:
' You this delegate in order to fill the grid from
' a thread other than the form's thread. See the HandleCallback
' procedure for more information.
Private Delegate Sub FillGridDelegate(ByVal reader As SqlDataReader)
' You need this delegate to update the status bar.
Private Delegate Sub DisplayStatusDelegate(ByVal Text As String)
' This flag ensures that the user does not attempt
' to restart the command or close the form while the
' asynchronous command is executing.
Private isExecuting As Boolean
Private Sub DisplayStatus(ByVal Text As String)
Me.Label1.Text = Text
End Sub
Private Sub FillGrid(ByVal reader As SqlDataReader)
Try
Dim table As New DataTable
table.Load(reader)
Me.DataGridView1.DataSource = table
DisplayStatus("Ready")
Catch ex As Exception
' Because you are guaranteed this procedure
' is running from within the form's thread,
' it can directly interact with members of the form.
DisplayStatus(String.Format("Ready (last attempt failed: {0})", ex.Message))
Finally
' Closing the reader also closes the connection,
' because this reader was created using the
' CommandBehavior.CloseConnection value.
If reader IsNot Nothing Then
reader.Close()
End If
End Try
End Sub
Private Sub HandleCallback(ByVal result As IAsyncResult)
Try
' Retrieve the original command object, passed
' to this procedure in the AsyncState property
' of the IAsyncResult parameter.
Dim command As SqlCommand = CType(result.AsyncState, SqlCommand)
Dim reader As SqlDataReader = command.EndExecuteReader(result)
' You may not interact with the form and its contents
' from a different thread, and this callback procedure
' is all but guaranteed to be running from a different thread
' than the form. Therefore you cannot simply call code that
' fills the grid, like this:
' FillGrid(reader)
' Instead, you must call the procedure from the form's thread.
' One simple way to accomplish this is to call the Invoke
' method of the form, which calls the delegate you supply
' from the form's thread.
Dim del As New FillGridDelegate(AddressOf FillGrid)
Me.Invoke(del, reader)
' Do not close the reader here, because it is being used in
' a separate thread. Instead, have the procedure you have
' called close the reader once it is done with it.
Catch ex As Exception
' Because you are now running code in a separate thread,
' if you do not handle the exception here, none of your other
' code catches the exception. Because there is none of
' your code on the call stack in this thread, there is nothing
' higher up the stack to catch the exception if you do not
' handle it here. You can either log the exception or
' invoke a delegate (as in the non-error case in this
' example) to display the error on the form. In no case
' can you simply display the error without executing a delegate
' as in the Try block here.
' You can create the delegate instance as you
' invoke it, like this:
Me.Invoke(New DisplayStatusDelegate(AddressOf DisplayStatus), _
"Error: " & ex.Message)
Finally
isExecuting = False
End Try
End Sub
Private Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
' If you do not include the Asynchronous Processing=true name/value pair,
' you wo not be able to execute the command asynchronously.
Return "Data Source=(local);Integrated Security=true;" & _
"Initial Catalog=AdventureWorks; Asynchronous Processing=true"
End Function
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
If isExecuting Then
MessageBox.Show(Me, "Already executing. Please wait until the current query " & _
"has completed.")
Else
Dim connection As SqlConnection
Dim command As SqlCommand
Try
DisplayStatus("Connecting...")
connection = New SqlConnection(GetConnectionString())
' To emulate a long-running query, wait for
' a few seconds before retrieving the real data.
command = New SqlCommand( _
"WAITFOR DELAY '0:0:5';" & _
"SELECT ProductID, Name, ListPrice, Weight FROM Production.Product", _
connection)
connection.Open()
DisplayStatus("Executing...")
isExecuting = True
' Although it is not required that you pass the
' SqlCommand object as the second parameter in the
' BeginExecuteReader call, doing so makes it easier
' to call EndExecuteReader in the callback procedure.
Dim callback As New AsyncCallback(AddressOf HandleCallback)
command.BeginExecuteReader(callback, command, _
CommandBehavior.CloseConnection)
Catch ex As Exception
DisplayStatus("Error: " & ex.Message)
If connection IsNot Nothing Then
connection.Close()
End If
End Try
End If
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, _
ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
If isExecuting Then
MessageBox.Show(Me, "Cannot close the form until " & _
"the pending asynchronous command has completed. Please wait...")
e.Cancel = True
End If
End Sub
End Class
Megjegyzések
A BeginExecuteReader metódus elindítja a sorokat visszaadó Transact-SQL utasítás vagy tárolt eljárás aszinkron végrehajtásának folyamatát, hogy más feladatok párhuzamosan fussanak az utasítás végrehajtása közben. Ha az utasítás befejeződött, a fejlesztőknek meg kell hívniuk a metódust a EndExecuteReader művelet befejezéséhez és a SqlDataReader parancs által visszaadott adatok lekéréséhez. A BeginExecuteReader metódus azonnal visszatér, de amíg a kód nem hajtja végre a megfelelő EndExecuteReader metódushívást, nem hajthat végre más hívásokat, amelyek szinkron vagy aszinkron végrehajtást indítanak ugyanahhoz SqlCommand az objektumhoz. Ha a EndExecuteReader parancs végrehajtása előtt hívja meg az objektumot, az SqlCommand a végrehajtás befejezéséig blokkolódik.
A callback paraméter lehetővé teszi egy meghatalmazott megadását AsyncCallback , amelyet az utasítás befejezésekor hív meg. A metódust meghívhatja ezen a EndExecuteReader delegálási eljáráson belül, vagy az alkalmazás bármely más helyről. Emellett a paraméter bármely stateObject objektumát átadhatja, a visszahívási eljárás pedig lekérheti ezeket az adatokat a AsyncState tulajdonság használatával.
A behavior paraméter lehetővé teszi a parancs és a kapcsolat viselkedését vezérlő beállítások megadását. Ezek az értékek kombinálhatók (a programozási nyelv operátorának Or használatával); a fejlesztők általában arra használják az CloseConnection értéket, hogy a kapcsolat a futtatókörnyezet SqlDataReader által bezárt állapotban legyen. A fejlesztők a SqlDataReader viselkedését is optimalizálhatják a SingleRow érték megadásával, ha előre ismert, hogy a Transact-SQL utasítás vagy a tárolt eljárás csak egyetlen sort ad vissza.
Vegye figyelembe, hogy a parancs szövegét és paramétereit a rendszer szinkron módon küldi el a kiszolgálónak. Ha nagy parancsot vagy több paramétert küld, ez a módszer blokkolhatja az írások során. A parancs elküldése után a metódus azonnal visszatér, anélkül, hogy választ vár a kiszolgálótól – vagyis az olvasások aszinkronok. Bár a parancsvégrehajtás aszinkron, az értéklekérés továbbra is szinkron. Ez azt jelenti, hogy a hívás blokkolhatja Read , ha több adatra van szükség, és a mögöttes hálózat olvasási műveletblokkja.
Mivel a visszahívási eljárás a Microsoft .NET közös nyelvi futtatókörnyezet által biztosított háttérszálból történik, nagyon fontos, hogy szigorú megközelítést alkalmazzon a többszálas interakciók alkalmazáson belüli kezelésére. Például nem használhatja az űrlap tartalmát a visszahívási eljáráson belül – ha frissítenie kell az űrlapot, a munka elvégzéséhez vissza kell váltania az űrlap szálára. A jelen témakörben szereplő példa ezt a viselkedést mutatja be.
A művelet végrehajtása során előforduló összes hiba kivételként jelenik meg a visszahívási eljárásban. A kivételt a visszahívási eljárásban kell kezelnie, nem a fő alkalmazásban. A visszahívási eljárás kivételeinek kezelésével kapcsolatos további információkért tekintse meg a jelen témakörben található példát.
Ha ExecuteReader vagy BeginExecuteReader használatával fér hozzá az XML-adatokhoz, SQL Server minden 2033 karakternél hosszabb XML-eredményt ad vissza 2033 karakternél hosszabb sorokban, egyenként 2033 karakter hosszúságú sorokban. Ennek a viselkedésnek a elkerülése érdekében használja ExecuteXmlReader vagy BeginExecuteXmlReader olvassa el a FOR XML-lekérdezéseket.
Ez a metódus figyelmen kívül hagyja a tulajdonságot CommandTimeout .
Lásd még
- Az adatok összekapcsolása és lekérése az ADO-ban.NET
A .NET-keretrendszer Data Provider használata SQL Server - ADO.NET áttekintése