語言

SqlCommand.BeginExecuteXmlReader 方法

定義

多載

名稱 Description
BeginExecuteXmlReader()

啟動非同步執行由此 SqlCommand 描述的 Transact-SQL 語句或儲存程序,並將結果以 XmlReader 物件形式回傳。

BeginExecuteXmlReader(AsyncCallback, Object)

啟動非同步執行由此 SqlCommand 描述的 Transact-SQL 語句或儲存程序,並以回調程序回傳結果 XmlReader 為物件。

BeginExecuteXmlReader()

來源:
SqlCommand.cs
來源:
SqlCommand.cs
來源:
SqlCommand.cs
來源:
SqlCommand.cs

啟動非同步執行由此 SqlCommand 描述的 Transact-SQL 語句或儲存程序,並將結果以 XmlReader 物件形式回傳。

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

傳回

可用 IAsyncResult 來輪詢或等待結果,或兩者兼用;此值在呼叫 EndExecuteXmlReader時也需用,該值回傳單一 XML 值。

例外狀況

  • 執行指令文字時發生的任何錯誤。
  • 串流操作中發生了一次超時。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

在串流操作中,物件或 發生StreamXmlReaderTextReader錯誤。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

Stream該 , XmlReader 或TextReader物件在串流操作中被關閉。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

範例

以下主控台應用程式開始非同步擷取 XML 資料的過程。 在等待結果的同時,這個簡單的應用程式會 IsCompleted 循環調查房產價值。 程序完成後,程式碼會擷取 XML 並顯示其內容。

using System;
using System.Data;
using Microsoft.Data.SqlClient;
using System.Xml;

class Class1
{
    static void Main()
    {
        // This example is not terribly effective, 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 Name, ListPrice FROM Production.Product " +
            "WHERE ListPrice < 100 " +
            "FOR XML AUTO, XMLDATA";

        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))
        {
            SqlCommand command = new SqlCommand(commandText, connection);

            connection.Open();
            IAsyncResult result = command.BeginExecuteXmlReader();

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

            XmlReader reader = command.EndExecuteXmlReader(result);
            DisplayProductInfo(reader);
        }
    }

    private static 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")
            {
                Console.WriteLine("{0}: {1:C}",
                    reader["Name"], Convert.ToSingle(reader["ListPrice"]));
            }
        }
    }

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

備註

此 BeginExecuteXmlReader() 方法啟動非同步執行一個 Transact-SQL 語句的過程,該語句以 XML 格式回傳資料列,讓其他任務能在該語句執行時同時執行。 當敘述完成後,開發者必須呼叫該 EndExecuteXmlReader(IAsyncResult) 方法以完成操作並取得指令回傳的 XML。 該 BeginExecuteXmlReader() 方法會立即回傳,但在程式碼執行對應 EndExecuteXmlReader(IAsyncResult) 的方法呼叫之前,不能執行任何對同一 SqlCommand 物件啟動同步或非同步執行的其他呼叫。 在指令執行完成前呼叫 , EndExecuteXmlReader 物件會阻塞 SqlCommand 直到執行完成。

此 CommandText 屬性通常指定一個具有有效 FOR XML 子句的 Transact-SQL 語句。 然而,也可以 CommandText 指定一個回傳 ntext 包含有效 XML 的資料的陳述句。

典型 BeginExecuteXmlReader() 的查詢格式可如以下 C# 範例所示:

SqlCommand command = new SqlCommand("SELECT ContactID, FirstName, LastName FROM dbo.Contact FOR XML AUTO, XMLDATA", SqlConn);

此方法也可用於取得單列單欄結果集。 此時若返回 EndExecuteXmlReader(IAsyncResult) 多列,方法會將 XmlReader 附加於第一列的值,並捨棄其餘結果集。

多重主動結果集(MARS)功能允許多個動作共用同一連線。

請注意,指令文字與參數是同步傳送到伺服器的。 若傳送大型指令或多個參數,此方法可能會在寫入時阻塞。 指令發送後,方法會立即返回,無需等待伺服器回應——也就是說,讀取是非同步的。 雖然指令執行是非同步的,但取值仍然是同步的。

由於此過載不支援回調程序,開發者需要利用方法返回的屬性IsCompleted輪詢指令是否完成IAsyncResult;或等待一個或多個指令完成,使用BeginExecuteXmlReader()返回AsyncWaitHandle的 屬性。IAsyncResult

如果您使用 ExecuteReader() 或 BeginExecuteReader() 存取 XML 資料,SQL Server 會以多列 2,033 字元返回任何長度超過 2,033 字元的 XML 結果。 為避免此行為,請使用 ExecuteXmlReader() 或 BeginExecuteXmlReader() 讀取 FOR XML 查詢。

此方法忽略了該 CommandTimeout 性質。

適用於

BeginExecuteXmlReader(AsyncCallback, Object)

來源:
SqlCommand.cs
來源:
SqlCommand.cs
來源:
SqlCommand.cs
來源:
SqlCommand.cs

啟動非同步執行由此 SqlCommand 描述的 Transact-SQL 語句或儲存程序,並以回調程序回傳結果 XmlReader 為物件。

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

參數

callback
AsyncCallback

當 AsyncCallback 指令執行完成時會被召喚的代理人。 隘口 null(在Microsoft Visual Basic中Nothing)表示不需要回撥。

stateObject
Object

一個由使用者定義的狀態物件,傳遞給回調程序。 利用 プロパティ AsyncState 從回調程序中擷取此物件。

傳回

可用 IAsyncResult 來輪詢、等待結果,或兩者兼具;當呼叫 時 EndExecuteXmlReader(IAsyncResult) ,這個值也會被要求,因為指令的結果會以 XML 形式回傳。

例外狀況

當 設定為 SqlDbType 時,會使用除 Binary 或 VarBinary 以外的 。ValueStream 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

-或-

SqlDbType除了 Char、NChar、NVarChar、VarChar 或 Xml,當 設定為 時,會使用其他 Char、Value、NVarChar、TextReader 或 Xml。

-或-

當 設定為 SqlDbType 時,會使用 Xml 以外的 。ValueXmlReader

執行指令文字時發生的任何錯誤。

-或-

串流操作中發生了一次超時。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

在 SqlConnection 串流操作中關閉或掉落。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

  • 或-

Microssoft.Data.SqlClient.SqlCommand.EnableOptimizedParameterBinding 設定為 true,且集合中新增 Parameters 了方向為 Output 或 InputOutput 的參數。

在串流操作中,物件或 發生 StreamXmlReaderTextReader 錯誤。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

Stream 該 , XmlReader 或TextReader物件在串流操作中被關閉。 欲了解更多串流資訊,請參閱 SqlClient 串流支援。

範例

下列 Windows 應用程式示範如何使用 BeginExecuteXmlReader 方法,來執行包含數秒延遲的 Transact-SQL 陳述式 (模擬長時間執行的命令)。 此範例將執行 SqlCommand 物件作為 stateObject 參數傳遞——這樣做使得從回調程序中取得 SqlCommand 物件變得簡單,程式碼便能呼叫 EndExecuteXmlReader 對應初始呼叫 BeginExecuteXmlReader的方法。

此範例展示了許多重要的技巧。 這包括呼叫一個從獨立執行緒與表單互動的方法。 此外,這個範例說明了你必須阻止使用者同時執行多次指令,以及如何確保表單在呼叫回調程序被呼叫前不會關閉。

若要設定此範例,請建立新的 Windows 應用程式。 在表單上加上一個控制點、Button一個控制點,再加ListBox一個Label控制點(接受每個控制項的預設名稱)。 在表單的類別中加入以下程式碼,並根據環境需要修改連接字串。

/* This does not compile, as multiple methods are missing.
// <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 SqlCommand_BeginExecuteXmlReaderAsync
{
    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 字元返回任何長度超過 2,033 字元的 XML 結果。 為避免此行為,請使用 ExecuteXmlReader 或 BeginExecuteXmlReader 讀取 FOR XML 查詢。

此方法忽略了該 CommandTimeout 性質。

另請參閱

適用於