SqlCommand.BeginExecuteReader 方法    
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
重载
| BeginExecuteReader() | 
						 启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行,并将结果作为 XmlReader 对象返回。  | 
        	
| BeginExecuteReader(CommandBehavior) | 
						 通过使用 CommandBehavior 值之一,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。  | 
        	
| BeginExecuteReader(AsyncCallback, Object) | 
						 通过使用回调过程,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行,并将结果作为 XmlReader 对象返回。  | 
        	
| BeginExecuteReader(AsyncCallback, Object, CommandBehavior) | 
						 使用 之一启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行
                | 
        	
BeginExecuteReader()
启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行,并将结果作为 XmlReader 对象返回。
public:
 IAsyncResult ^ BeginExecuteReader();
	public IAsyncResult BeginExecuteReader ();
	member this.BeginExecuteReader : unit -> IAsyncResult
	Public Function BeginExecuteReader () As IAsyncResult
	返回
一个 IAsyncResult ,可用于轮询或等待结果,或两者兼而有之;调用时也需要此值
              EndExecuteXmlReader ,它返回单个 XML 值。
例外
SqlDbType当 设置为 Stream 时Value,使用 Binary 或 VarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- 或 -
SqlDbType设置为 时ValueTextReader ,使用了 Char、NChar、NVarChar、VarChar 或 Xml 以外的其他项。
-或-
流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- or -
<xref data-throw-if-not-resolved="true" uid="Microssoft.Data.SqlClient.SqlCommand.EnableOptimizedParameterBinding"></xref>
is set to true and a parameter with direction Output or InputOutput has been added to the <xref data-throw-if-not-resolved="true" uid="Microsoft.Data.SqlClient.SqlCommand.Parameters"></xref> collection.
		在流式处理操作期间, XmlReader 或 TextReader 对象中Stream发生错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
在StreamXmlReader流式处理操作期间, 或 TextReader 对象已关闭。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
示例
以下控制台应用程序启动异步检索 XML 数据的过程。 在等待结果时,此简单应用程序位于循环中,调查 IsCompleted 属性值。 该过程完成后,代码将检索 XML 并显示其内容。
[!code-csharp[SqlCommand_BeginExecuteXmlReader#1] ( (~/../sqlclient/doc/samples/SqlCommand_BeginExecuteXmlReader.cs) ]
注解
方法 BeginExecuteXmlReader 启动异步执行 Transact-SQL 语句的过程,该语句将行作为 XML 返回,以便其他任务可以在语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteXmlReader 方法来完成操作并检索命令返回的 XML。 方法 BeginExecuteXmlReader 会立即返回,但在代码执行相应的 EndExecuteXmlReader 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 
              EndExecuteXmlReader在命令执行完成之前调用 会导致SqlCommand对象阻塞,直到执行完成。
属性 CommandText 通常指定具有有效 FOR XML 子句的 Transact-SQL 语句。 但是, CommandText 也可以指定返回包含有效 XML 的数据的 ntext 语句。
典型 BeginExecuteXmlReader 查询的格式可以设置为以下 C# 示例中的格式:
SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM dbo.Contact FOR XML AUTO, XMLDATA", SqlConn);
此方法还可用于检索单行、单列结果集。 在这种情况下,如果返回了多行,该方法 EndExecuteXmlReader 会将 XmlReader 附加到第一行的值,并放弃结果集的其余部分。
MARS) 功能 (多个活动结果集允许多个操作使用同一连接。
请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间阻止。 发送命令后,方法会立即返回,无需等待服务器的答案,即读取是异步的。 虽然命令执行是异步的,但值提取仍然是同步的。
由于此重载不支持回调过程,因此开发人员需要使用 方法返回的 的 IAsyncResult 属性轮询以确定命令是否已完成IsCompleted;或者使用AsyncWaitHandle返回IAsyncResult的 的 属性等待一个或多个命令完成。BeginExecuteXmlReader
如果使用 ExecuteReader 或 BeginExecuteReader 访问 XML 数据,SQL Server将返回长度超过 2,033 个字符的任何 XML 结果,每行 2,033 个字符。 若要避免此行为,请使用 ExecuteXmlReader 或 BeginExecuteXmlReader 读取 FOR XML 查询。
此方法忽略 CommandTimeout 属性。
适用于
BeginExecuteReader(CommandBehavior)
通过使用 CommandBehavior 值之一,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。
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
	参数
- behavior
 - CommandBehavior
 
CommandBehavior 值之一,指示用于语句执行和数据检索的选项。
返回
IAsyncResult可用于轮询和/或等待结果的 ;调用 EndExecuteReader(IAsyncResult) 时也需要此值,后者返回SqlDataReader可用于检索返回的行的实例。
例外
SqlDbType当 设置为 Stream 时Value,使用 Binary 或 VarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- 或 -
SqlDbType设置为 时ValueTextReader ,使用了 Char、NChar、NVarChar、VarChar 或 Xml 以外的其他项。
-或-
流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- or -
<xref data-throw-if-not-resolved="true" uid="Microssoft.Data.SqlClient.SqlCommand.EnableOptimizedParameterBinding"></xref>
is set to true and a parameter with direction Output or InputOutput has been added to the <xref data-throw-if-not-resolved="true" uid="Microsoft.Data.SqlClient.SqlCommand.Parameters"></xref> collection.
		在流式处理操作期间, XmlReader 或 TextReader 对象中Stream发生错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
在StreamXmlReader流式处理操作期间, 或 TextReader 对象已关闭。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
示例
以下控制台应用程序将启动异步检索数据读取器的过程。 在等待结果时,此简单应用程序位于循环中,调查 IsCompleted 属性值。 该过程完成后,代码将 SqlDataReader 检索 并显示其内容。
此示例还传递 CommandBehavior.CloseConnection 行为参数中的 和 CommandBehavior.SingleRow 值,导致连接关闭,返回的 SqlDataReader 关闭,并针对单行结果进行优化。
// <Snippet1>
using System;
using System.Data;
using Microsoft.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. 
        return "Data Source=(local);Integrated Security=true;" +
            "Initial Catalog=AdventureWorks";
    }
}
// </Snippet1>
    	注解
方法 BeginExecuteReader 启动异步执行返回行的 Transact-SQL 语句或存储过程的过程,以便其他任务可以在语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteReader 方法来完成操作并检索 SqlDataReader 命令返回的 。 方法 BeginExecuteReader 会立即返回,但在代码执行相应的 EndExecuteReader 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 EndExecuteReader在命令执行完成之前调用 会导致SqlCommand对象阻塞,直到执行完成。
参数 behavior 允许你指定用于控制命令行为及其连接的选项。 可以使用编程语言的 OR 运算符) 将这些值组合在一起 (;通常,开发人员使用 CommandBehavior.CloseConnection 值来确保在 关闭 时 SqlDataReader 运行时关闭连接。
请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间阻止。 发送命令后,方法会立即返回,无需等待服务器的答案,即读取是异步的。 虽然命令执行是异步的,但值提取仍然是同步的。 这意味着,如果需要更多数据并且基础网络的读取操作阻止,则对 的调用 Read 可能会阻止。
由于此重载不支持回调过程,因此开发人员必须使用 方法返回的 的 IAsyncResult 属性轮询以确定命令是否已完成IsCompleted;或使用返回IAsyncResult的 的 属性等待一个或多个命令AsyncWaitHandle完成。BeginExecuteNonQuery
如果使用 ExecuteReader 或 BeginExecuteReader 访问 XML 数据,SQL Server将返回长度超过 2,033 个字符的任何 XML 结果,每行 2,033 个字符。 若要避免此行为,请使用 ExecuteXmlReader 或 BeginExecuteXmlReader 读取 FOR XML 查询。
此方法忽略 CommandTimeout 属性。
适用于
BeginExecuteReader(AsyncCallback, Object)
通过使用回调过程,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行,并将结果作为 XmlReader 对象返回。
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
	参数
- callback
 - AsyncCallback
 
命令执行完成时调用的 AsyncCallback 委托。 通过
              null ( Nothing Microsoft Visual Basic) 中指示不需要回调。
- stateObject
 - Object
 
传递到回调过程的用户定义的状态对象。 使用 AsyncState 属性从回调过程内检索此对象。
返回
可用于轮询和/或等待结果的 IAsyncResult;当调用 EndExecuteXmlReader(IAsyncResult) 时,也需要该值,用于将命令的结果作为 XML 返回。
例外
SqlDbType当 设置为 Stream 时Value,使用 Binary 或 VarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- 或 -
设置为 SqlDbType 时ValueTextReader ,使用了 Char、NChar、NVarChar、VarChar 或 Xml 以外的 。
-或-
流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- or -
<xref data-throw-if-not-resolved="true" uid="Microssoft.Data.SqlClient.SqlCommand.EnableOptimizedParameterBinding"></xref>
is set to true and a parameter with direction Output or InputOutput has been added to the <xref data-throw-if-not-resolved="true" uid="Microsoft.Data.SqlClient.SqlCommand.Parameters"></xref> collection.
		在流式处理操作期间, XmlReader 或 TextReader 对象中Stream发生错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
在 Stream 流式处理操作期间关闭了 、 XmlReader 或 TextReader 对象。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
示例
以下 Windows 应用程序演示如何使用 BeginExecuteXmlReader 方法,以执行包含几秒钟延迟(模拟长时间运行的命令)的 Transact-SQL 语句。 此示例将正在执行 SqlCommand 的对象作为 stateObject 参数进行传递-这样做使得从回调过程中检索 SqlCommand 对象变得简单,以便代码可以调用 EndExecuteXmlReader 对应于对 的初始调用 BeginExecuteXmlReader的方法。
此示例演示了许多重要的技术。 这包括从单独的线程调用与窗体交互的方法。 此外,此示例演示了如何阻止用户多次同时执行命令,以及如何在调用回调过程之前确保窗体不会关闭。
若要设置此示例,请创建新的 Windows 应用程序。 将 Button 控件、 ListBox 控件和 Label 控件放在窗体上, (接受每个控件的默认名称) 。 将以下代码添加到窗体的 类,根据环境需要修改连接字符串。
// <Snippet1>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Data.SqlClient;
using System.Xml;
namespace Microsoft.AdoDotNet.CodeSamples
{
    public partial class Form1 : Form
    {
        // Hook up the form's Load event handler and then add 
        // this code to the form's class:
        // You need these delegates in order to display text from a thread
        // other than the form's thread. See the HandleCallback
        // procedure for more information.
        private delegate void DisplayInfoDelegate(string Text);
        private delegate void DisplayReaderDelegate(XmlReader reader);
        private bool isExecuting;
        // This example maintains the connection object 
        // externally, so that it is available for closing.
        private SqlConnection connection;
        public Form1()
        {
            InitializeComponent();
        }
        private string GetConnectionString()
        {
            // To avoid storing the connection string in your code, 
            // you can retrieve it from a configuration file. 
            return "Data Source=(local);Integrated Security=true;" +
            "Initial Catalog=AdventureWorks";
        }
        private void DisplayStatus(string Text)
        {
            this.label1.Text = Text;
        }
        private void ClearProductInfo()
        {
            // Clear the list box.
            this.listBox1.Items.Clear();
        }
        private void DisplayProductInfo(XmlReader reader)
        {
            // Display the data within the reader.
            while (reader.Read())
            {
                // Skip past items that are not from the correct table.
                if (reader.LocalName.ToString() == "Production.Product")
                {
                    this.listBox1.Items.Add(String.Format("{0}: {1:C}",
                        reader["Name"], Convert.ToDecimal(reader["ListPrice"])));
                }
            }
            DisplayStatus("Ready");
        }
        private void Form1_FormClosing(object sender,
            System.Windows.Forms.FormClosingEventArgs e)
        {
            if (isExecuting)
            {
                MessageBox.Show(this, "Cannot close the form until " +
                    "the pending asynchronous command has completed. Please wait...");
                e.Cancel = 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
                {
                    ClearProductInfo();
                    DisplayStatus("Connecting...");
                    connection = new SqlConnection(GetConnectionString());
                    // To emulate a long-running query, wait for 
                    // a few seconds before working with the data.
                    string commandText =
                        "WAITFOR DELAY '00:00:03';" +
                        "SELECT Name, ListPrice FROM Production.Product " +
                        "WHERE ListPrice < 100 " +
                        "FOR XML AUTO, XMLDATA";
                    command = new SqlCommand(commandText, connection);
                    connection.Open();
                    DisplayStatus("Executing...");
                    isExecuting = true;
                    // Although it is not required that you pass the 
                    // SqlCommand object as the second parameter in the 
                    // BeginExecuteXmlReader call, doing so makes it easier
                    // to call EndExecuteXmlReader in the callback procedure.
                    AsyncCallback callback = new AsyncCallback(HandleCallback);
                    command.BeginExecuteXmlReader(callback, command);
                }
                catch (Exception ex)
                {
                    isExecuting = false;
                    DisplayStatus(string.Format("Ready (last error: {0})", ex.Message));
                    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;
                XmlReader reader = command.EndExecuteXmlReader(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. 
                // 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. 
                DisplayReaderDelegate del = new DisplayReaderDelegate(DisplayProductInfo);
                this.Invoke(del, reader);
            }
            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 none of 
                // your code is 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 DisplayInfoDelegate(DisplayStatus),
                String.Format("Ready(last error: {0}", ex.Message));
            }
            finally
            {
                isExecuting = false;
                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 System.Windows.Forms.
                FormClosingEventHandler(this.Form1_FormClosing);
        }
    }
}
// </Snippet1>
    	注解
方法 BeginExecuteXmlReader 启动异步执行 Transact-SQL 语句或将行作为 XML 返回的存储过程的过程,以便其他任务可以在该语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteXmlReader 方法来完成操作并检索请求的 XML 数据。 方法 BeginExecuteXmlReader 会立即返回,但在代码执行相应的 EndExecuteXmlReader 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 在 EndExecuteXmlReader 命令的执行完成之前调用 会导致 SqlCommand 对象阻塞,直到执行完成。
属性 CommandText 通常使用有效的 FOR XML 子句指定 Transact-SQL 语句。 但是, CommandText 还可以指定返回包含有效 XML 的数据的语句。 此方法还可用于检索单行、单列结果集。 在这种情况下,如果返回多行,该方法 EndExecuteXmlReader 会将 XmlReader 附加到第一行的值,并放弃结果集的其余部分。
典型 BeginExecuteXmlReader 查询的格式可以如以下 C# 示例中所示:
SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM Contact FOR XML AUTO, XMLDATA", SqlConn);
此方法还可用于检索单行、单列结果集。 在这种情况下,如果返回多行,该方法 EndExecuteXmlReader 会将 XmlReader 附加到第一行的值,并放弃结果集的其余部分。
MARS) 功能 (多个活动结果集允许多个操作使用同一连接。
使用 callback 参数可以指定在 AsyncCallback 语句完成时调用的委托。 可以从此委托过程内或应用程序内的任何其他位置调用 EndExecuteXmlReader 方法。 此外,可以传递 参数中的任何 stateObject 对象,并且回调过程可以使用 属性检索此信息 AsyncState 。
请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间受阻。 发送命令后,方法会立即返回,而无需等待服务器的答案,即读取是异步的。
在执行操作期间发生的所有错误都将作为回调过程中的异常引发。 必须在回调过程中处理异常,而不是在主应用程序中处理。 有关在回调过程中处理异常的其他信息,请参阅本主题中的示例。
如果使用 ExecuteReader 或 BeginExecuteReader 访问 XML 数据,SQL Server将返回长度超过 2,033 个字符的任何 XML 结果,每行包含 2,033 个字符。 若要避免此行为,请使用 ExecuteXmlReader 或 BeginExecuteXmlReader 读取 FOR XML 查询。
此方法忽略 属性 CommandTimeout 。
另请参阅
适用于
BeginExecuteReader(AsyncCallback, Object, CommandBehavior)
使用之一启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行
              CommandBehavior 值,并从服务器检索一个或多个结果集,给定回调过程和状态信息。
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
	参数
- callback
 - AsyncCallback
 
命令执行完成时调用的 AsyncCallback 委托。 通过
              null ( Nothing Microsoft Visual Basic) 中指示不需要回调。
- stateObject
 - Object
 
传递到回调过程的用户定义的状态对象。 使用 AsyncState 属性从回调过程内检索此对象。
- behavior
 - CommandBehavior
 
CommandBehavior 值之一,指示用于语句执行和数据检索的选项。
返回
IAsyncResult可用于轮询或等待结果或两者兼有的 ;调用 EndExecuteReader(IAsyncResult) 时也需要此值,后者返回SqlDataReader可用于检索返回的行的 实例。
例外
当 SqlDbType 设置为 Stream 时Value,使用了 Binary 或 VarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- 或 -
设置为 SqlDbType 时ValueTextReader ,使用了 Char、NChar、NVarChar、VarChar 或 Xml 以外的 。
-或-
流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
- or -
<xref data-throw-if-not-resolved="true" uid="Microssoft.Data.SqlClient.SqlCommand.EnableOptimizedParameterBinding"></xref>
is set to true and a parameter with direction Output or InputOutput has been added to the <xref data-throw-if-not-resolved="true" uid="Microsoft.Data.SqlClient.SqlCommand.Parameters"></xref> collection.
		在流式处理操作期间, XmlReader 或 TextReader 对象中Stream发生错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
在 Stream 流式处理操作期间关闭了 、 XmlReader 或 TextReader 对象。 有关流式处理的详细信息,请参阅 SqlClient 流支持。
示例
以下 Windows 应用程序演示如何使用 BeginExecuteReader 方法,以执行包含几秒钟延迟(模拟长时间运行的命令)的 Transact-SQL 语句。 由于示例以异步方式执行命令,因此窗体在等待结果时保持响应。 此示例将正在执行 SqlCommand 的对象作为 stateObject 参数传递;这样做使从回调过程中检索 SqlCommand 对象变得简单,以便代码可以调用 EndExecuteReader 对应于对 的初始调用 BeginExecuteReader的方法。
此示例演示了许多重要的技术。 这包括从单独的线程调用与窗体交互的方法。 此外,此示例还演示了如何阻止用户多次同时执行命令,以及如何在调用回调过程之前确保窗体不会关闭。
若要设置此示例,请创建新的 Windows 应用程序。 Button将控件、DataGridView控件和Label控件放在窗体上, (接受每个控件) 的默认名称。 将以下代码添加到窗体的 类,根据环境需要修改连接字符串。
此示例传递 CommandBehavior.CloseConnection 参数中的 behavior 值,导致返回的 SqlDataReader 在关闭时自动关闭其连接。
// <Snippet1>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.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. 
            return "Data Source=(local);Integrated Security=true;" +
                "Initial Catalog=AdventureWorks";
        }
        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;
            }
        }
    }
}
// </Snippet1>
    	注解
方法 BeginExecuteReader 启动异步执行 Transact-SQL 语句或返回行的存储过程的过程,以便其他任务可以在语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteReader 方法来完成操作并检索 SqlDataReader 命令返回的 。 方法 BeginExecuteReader 会立即返回,但在代码执行相应的 EndExecuteReader 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 在 EndExecuteReader 命令的执行完成之前调用 会导致 SqlCommand 对象阻塞,直到执行完成。
使用 callback 参数可以指定在 AsyncCallback 语句完成时调用的委托。 可以从此委托过程内或应用程序内的任何其他位置调用 EndExecuteReader 方法。 此外,可以传递 参数中的任何 stateObject 对象,并且回调过程可以使用 属性检索此信息 AsyncState 。
使用 behavior 参数可以指定控制命令行为及其连接的选项。 可以使用编程语言的 Or 运算符) 将这些值组合在一起 (;通常,开发人员使用 CloseConnection 值来确保在 关闭 时 SqlDataReader 运行时关闭连接。 当事先知道 Transact-SQL 语句或存储过程仅返回一行时,开发人员还可以通过指定 SingleRow 值来优化 的行为SqlDataReader。
请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间受阻。 发送命令后,方法会立即返回,而无需等待服务器的答案,即读取是异步的。 虽然命令执行是异步的,但值提取仍然是同步的。 这意味着,如果需要更多数据,并且基础网络的读取操作阻止,则对 的调用 Read 可能会受阻。
由于回调过程是从 Microsoft .NET 公共语言运行时提供的后台线程中执行的,因此请务必采用严格的方法来处理应用程序中的跨线程交互。 例如,您不得从回调过程中与窗体的内容进行交互 -- 如果必须更新窗体,则必须切换回窗体的线程才能完成工作。 本主题中的示例演示了此行为。
在执行操作期间发生的所有错误都将作为回调过程中的异常引发。 必须在回调过程中处理异常,而不是在主应用程序中处理。 有关在回调过程中处理异常的其他信息,请参阅本主题中的示例。
如果使用 ExecuteReader 或 BeginExecuteReader 访问 XML 数据,SQL Server将返回长度超过 2,033 个字符的任何 XML 结果,每行包含 2,033 个字符。 若要避免此行为,请使用 ExecuteXmlReader 或 BeginExecuteXmlReader 读取 FOR XML 查询。
此方法忽略 属性 CommandTimeout 。