使用英语阅读

通过


SqlCommand.BeginExecuteNonQuery 方法

定义

启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。

重载

BeginExecuteNonQuery()

启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。

BeginExecuteNonQuery(AsyncCallback, Object)

在给定回调过程和状态信息的情况下,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。

BeginExecuteNonQuery()

Source:
System.Data.SqlClient.notsupported.cs

启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。

C#
public IAsyncResult BeginExecuteNonQuery();

返回

可用于轮询和/或等待结果的 IAsyncResult;当调用可返回受影响的行数的 EndExecuteNonQuery(IAsyncResult) 时,也需要该值。

例外

Value 设置为 Stream 时,使用的是 SqlDbType 而不是 Binary 或 VarBinary。 有关流式处理的详细信息,请参阅 SqlClient 流支持

- 或 -

设置为 SqlDbTypeValueTextReader,使用了 CharNCharNVarCharVarCharXml 以外的 。

- 或 -

Value 设置为 XmlReader 时,使用的是 SqlDbType 而不是 Xml

执行命令文本时出现的任何错误。

- 或 -

流式处理操作期间发生了超时。 有关流式处理的详细信息,请参阅 SqlClient 流支持

名称/值对“Asynchronous Processing=true”未包含在为此 SqlCommand 定义连接的连接字符串中。

- 或 -

流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持

流式处理操作期间在 StreamXmlReaderTextReader 对象中出现了错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持

流式处理操作期间关闭了 StreamXmlReaderTextReader 对象。 有关流式处理的详细信息,请参阅 SqlClient 流支持

示例

以下控制台应用程序在 AdventureWorks 示例数据库中创建更新数据,以异步方式执行其工作。 为了模拟长时间运行的进程,此示例在命令文本中插入一个 WAITFOR 语句。 通常,你不会费力使命令运行速度变慢,但在这种情况下,这样做可以更轻松地演示异步行为。

C#
using System.Data.SqlClient;

class Class1
{
    static void Main()
    {
        // This is a simple example that demonstrates the usage of the
        // BeginExecuteNonQuery functionality.
        // The WAITFOR statement simply adds enough time to prove the
        // asynchronous nature of the command.

        string commandText =
            "UPDATE Production.Product SET ReorderPoint = ReorderPoint + 1 " +
            "WHERE ReorderPoint Is Not Null;" +
            "WAITFOR DELAY '0:0:3';" +
            "UPDATE Production.Product SET ReorderPoint = ReorderPoint - 1 " +
            "WHERE ReorderPoint Is Not Null";

        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
            {
                int count = 0;
                SqlCommand command = new SqlCommand(commandText, connection);
                connection.Open();

                IAsyncResult result = command.BeginExecuteNonQuery();
                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);
                }
                Console.WriteLine("Command complete. Affected {0} rows.",
                    command.EndExecuteNonQuery(result));
            }
            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 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=SSPI;" +
            "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
    }
}

注解

方法 BeginExecuteNonQuery 启动异步执行 Transact-SQL 语句或不返回行的存储过程的过程,以便其他任务可以在该语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteNonQuery 方法来完成操作。 方法 BeginExecuteNonQuery 会立即返回,但在代码执行相应的 EndExecuteNonQuery 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 在 EndExecuteNonQuery 命令的执行完成之前调用 会导致 SqlCommand 对象阻塞,直到执行完成。

请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间受阻。 发送命令后,方法会立即返回,而无需等待服务器的答案,即读取是异步的。

由于此重载不支持回调过程,因此开发人员必须使用 方法返回的 的 IAsyncResult 属性轮询以确定命令是否已完成IsCompleted;或者使用AsyncWaitHandle返回IAsyncResult的 的 属性等待一个或多个命令完成。BeginExecuteNonQuery

此方法忽略 CommandTimeout 属性。

另请参阅

适用于

.NET 10 (package-provided) 和其他版本
产品 版本
.NET 6 (package-provided), 7 (package-provided), 8 (package-provided), 9 (package-provided), 10 (package-provided)
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0 (package-provided)

BeginExecuteNonQuery(AsyncCallback, Object)

Source:
System.Data.SqlClient.notsupported.cs

在给定回调过程和状态信息的情况下,启动此 SqlCommand 描述的 Transact-SQL 语句或存储过程的异步执行。

C#
public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback, object stateObject);

参数

callback
AsyncCallback

命令执行完成时调用的 AsyncCallback 委托。 传递 null(在 Microsoft Visual Basic 中为 Nothing)以指示不需要回调。

stateObject
Object

传递到回调过程的用户定义的状态对象。 使用 AsyncState 属性从回调过程内检索此对象。

返回

可用于轮询和/或等待结果的 IAsyncResult;当调用可返回受影响的行数的 EndExecuteNonQuery(IAsyncResult) 时,也需要该值。

例外

Value 设置为 Stream 时,使用的是 SqlDbType 而不是 Binary 或 VarBinary。 有关流式处理的详细信息,请参阅 SqlClient 流支持

- 或 -

设置为 SqlDbTypeValueTextReader,使用了 CharNCharNVarCharVarCharXml 以外的 。

- 或 -

Value 设置为 XmlReader 时,使用的是 SqlDbType 而不是 Xml

执行命令文本时出现的任何错误。

- 或 -

流式处理操作期间发生了超时。 有关流式处理的详细信息,请参阅 SqlClient 流支持

名称/值对“Asynchronous Processing=true”未包含在为此 SqlCommand 定义连接的连接字符串中。

- 或 -

流式处理操作期间关闭或删除了 SqlConnection。 有关流式处理的详细信息,请参阅 SqlClient 流支持

流式处理操作期间在 StreamXmlReaderTextReader 对象中出现了错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持

流式处理操作期间关闭了 StreamXmlReaderTextReader 对象。 有关流式处理的详细信息,请参阅 SqlClient 流支持

示例

以下 Windows 应用程序演示如何使用 BeginExecuteNonQuery 方法,执行包含几秒钟延迟的 Transact-SQL 语句, (模拟长时间运行的命令) 。

此示例演示了许多重要的技术。 这包括从单独的线程调用与窗体交互的方法。 此外,此示例演示了如何阻止用户多次同时执行命令,以及如何确保在调用回调过程之前窗体不会关闭。

若要设置此示例,请创建新的 Windows 应用程序。 Button将控件和Label控件放在窗体上, (接受每个控件) 的默认名称。 将以下代码添加到窗体的 类,根据环境需要修改连接字符串。

C#
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:
        private void Form1_Load(object sender, EventArgs e)
        {
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.FormClosing += new System.Windows.Forms.
                FormClosingEventHandler(this.Form1_FormClosing);
        }

        // You need this delegate in order to display text from a thread
        // other than the form's thread. See the HandleCallback
        // procedure for more information.
        // This same delegate matches both the DisplayStatus
        // and DisplayResults methods.
        private delegate void DisplayInfoDelegate(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;

        // This example maintains the connection object
        // externally, so that it is available for closing.
        private SqlConnection connection;

        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";
        }

        private void DisplayStatus(string Text)
        {
            this.label1.Text = Text;
        }

        private void DisplayResults(string Text)
        {
            this.label1.Text = Text;
            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
                {
                    DisplayResults("");
                    DisplayStatus("Connecting...");
                    connection = new SqlConnection(GetConnectionString());
                    // To emulate a long-running query, wait for
                    // a few seconds before working with the data.
                    // This command does not do much, but that's the point--
                    // it does not change your data, in the long run.
                    string commandText =
                        "WAITFOR DELAY '0:0:05';" +
                        "UPDATE Production.Product SET ReorderPoint = ReorderPoint + 1 " +
                        "WHERE ReorderPoint Is Not Null;" +
                        "UPDATE Production.Product SET ReorderPoint = ReorderPoint - 1 " +
                        "WHERE ReorderPoint Is Not Null";

                    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
                    // BeginExecuteNonQuery call, doing so makes it easier
                    // to call EndExecuteNonQuery in the callback procedure.
                    AsyncCallback callback = new AsyncCallback(HandleCallback);
                    command.BeginExecuteNonQuery(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;
                int rowCount = command.EndExecuteNonQuery(result);
                string rowText = " rows affected.";
                if (rowCount == 1)
                {
                    rowText = " row affected.";
                }
                rowText = rowCount + rowText;

                // 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
                // displays the results, like this:
                // DisplayResults(rowText)

                // 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.
                DisplayInfoDelegate del = new DisplayInfoDelegate(DisplayResults);
                this.Invoke(del, rowText);
            }
            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();
                }
            }
        }
    }
}

注解

方法 BeginExecuteNonQuery 启动异步执行 Transact-SQL 语句或不返回行的存储过程的过程,以便其他任务可以在该语句执行时并发运行。 语句完成后,开发人员必须调用 EndExecuteNonQuery 方法来完成操作。 方法 BeginExecuteNonQuery 会立即返回,但在代码执行相应的 EndExecuteNonQuery 方法调用之前,它不得执行针对同 SqlCommand 一对象启动同步或异步执行的任何其他调用。 在 EndExecuteNonQuery 命令的执行完成之前调用 会导致 SqlCommand 对象阻塞,直到执行完成。

使用 callback 参数可以指定在 AsyncCallback 语句完成时调用的委托。 可以从此委托过程内或应用程序内的任何其他位置调用 EndExecuteNonQuery 方法。 此外,可以传递 参数中的任何 asyncStateObject 对象,并且回调过程可以使用 属性检索此信息 AsyncState

请注意,命令文本和参数以同步方式发送到服务器。 如果发送了大型命令或多个参数,此方法可能会在写入期间受阻。 发送命令后,方法会立即返回,而无需等待服务器的答案,即读取是异步的。

由于回调过程是从 Microsoft .NET 公共语言运行时提供的后台线程中执行的,因此请务必采用严格的方法来处理应用程序中的跨线程交互。 例如,不得在回调过程中与表单的内容进行交互;如果必须更新窗体,则必须切换回窗体的线程才能完成工作。 本主题中的示例演示了此行为。

在执行操作期间发生的所有错误都将作为回调过程中的异常引发。 必须在回调过程中处理异常,而不是在main应用程序中处理。 有关在回调过程中处理异常的其他信息,请参阅本主题中的示例。

此方法忽略 CommandTimeout 属性。

另请参阅

适用于

.NET 10 (package-provided) 和其他版本
产品 版本
.NET 6 (package-provided), 7 (package-provided), 8 (package-provided), 9 (package-provided), 10 (package-provided)
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0 (package-provided)