Share via


SqlCommand.BeginExecuteNonQuery 方法

定义

重载

BeginExecuteNonQuery()

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

BeginExecuteNonQuery(AsyncCallback, Object)

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

BeginExecuteNonQuery()

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

public:
 IAsyncResult ^ BeginExecuteNonQuery();
public IAsyncResult BeginExecuteNonQuery ();
member this.BeginExecuteNonQuery : unit -> IAsyncResult
Public Function BeginExecuteNonQuery () As IAsyncResult

返回

一个 IAsyncResult ,可用于轮询或等待结果,或两者兼而有之;调用 EndExecuteNonQuery(IAsyncResult) 时也需要此值,后者返回受影响的行数。

例外

SqlDbType当 设置为 StreamValue,使用 BinaryVarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持

- 或 -

SqlDbType设置为 时ValueTextReader ,使用了 CharNCharNVarCharVarCharXml 以外的其他项。

-或-

SqlDbType设置为 时ValueXmlReader ,使用了 Xml 以外的 。

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

- 或 -

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

流式处理操作期间关闭或删除了 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.

在流式处理操作期间, XmlReaderTextReader 对象中Stream发生错误。 有关流式处理的详细信息,请参阅 SqlClient 流支持

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

示例

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

// <Snippet1>
using System;
using System.Data;
using Microsoft.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. 

        return "Data Source=(local);Integrated Security=SSPI;" +
            "Initial Catalog=AdventureWorks";
    }
}
// </Snippet1>

注解

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

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

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

此方法忽略 CommandTimeout 属性。

适用于

BeginExecuteNonQuery(AsyncCallback, Object)

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

public:
 IAsyncResult ^ BeginExecuteNonQuery(AsyncCallback ^ callback, System::Object ^ stateObject);
public IAsyncResult BeginExecuteNonQuery (AsyncCallback callback, object stateObject);
member this.BeginExecuteNonQuery : AsyncCallback * obj -> IAsyncResult
Public Function BeginExecuteNonQuery (callback As AsyncCallback, stateObject As Object) As IAsyncResult

参数

callback
AsyncCallback

命令执行完成时调用的 AsyncCallback 委托。 通过nullNothing ( Microsoft Visual Basic) 中指示不需要回调。

stateObject
Object

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

返回

一个 IAsyncResult ,可用于轮询或等待结果,或两者兼而有之;调用 EndExecuteNonQuery(IAsyncResult) 时也需要此值,后者返回受影响的行数。

例外

SqlDbType当 设置为 StreamValue,使用 BinaryVarBinary 以外的 。 有关流式处理的详细信息,请参阅 SqlClient 流支持

- 或 -

SqlDbType设置为 时ValueTextReader ,使用了 CharNCharNVarCharVarCharXml 以外的其他项。

-或-

SqlDbType设置为 时ValueXmlReader ,使用了 Xml 以外的 。

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

- 或 -

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

流式处理操作期间关闭或删除了 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.

示例

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

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

若要设置此示例,请创建新的 Windows 应用程序。 Button将控件和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;

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. 

            return "Data Source=(local);Integrated Security=true;" +
                "Initial Catalog=AdventureWorks";
        }

        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();
                }
            }
        }
    }
}
// </Snippet1>

注解

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

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

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

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

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

此方法忽略 CommandTimeout 属性。

适用于