簡體   English   中英

如何在ASP.NET Web服務中執行SQL事務異步

[英]How to execute SQL transaction Async in ASP.NET webservice

我有web服務,有很多連接。 我用過這段代碼:

IAsyncResult result = sqlCommand.BeginExecuteNonQuery();
while (!result.IsCompleted)
{
   System.Threading.Thread.Sleep(500);
}
sqlCommand.EndExecuteNonQuery(result);

我認為這不是最好的方法,因為我稱之為Sleep() PS。 這種方法會降低WebService和服務器的性能

UPDATE2:我嘗試更多地描述我的代碼:我有WebClient和2個事件( ProgressChangedDownloadCompleted

[WebMethod]
public void DonwloadFromRemoteServer(string uniqueId, string url)
{
    if (!Directory.Exists(uniqueId))
        Directory.CreateDirectory(uniqueId);

    WebClient wc = new WebClient();

    wc.DownloadProgressChanged += (sender, args) => wc_DownloadProgressChanged(sender, args, uniqueId, Path.GetFileName(url));

    wc.DownloadFileCompleted += (sender, args) => wc_DownloadFileCompleted(sender, args, uniqueId, Path.GetFileName(url));
    wc.DownloadFileAsync(new Uri(url), String.Format("{0}\\{1}", uniqueId, Path.GetFileName(url)));
}

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e, string uniqueId, string fileName)
{
    SqlConnection connection = new SqlConnection("Data Source=.\\SQLSERVER;Initial Catalog=XRingtoneDB;Integrated Security=True;Asynchronous Processing=true");
    connection.Open();
    SqlCommand sqlCommand = new SqlCommand();
    sqlCommand.Connection = connection;
    sqlCommand.CommandText = String.Format("IF NOT EXISTS(SELECT uniqueId FROM downloads WHERE uniqueID = '{0}') " +
                                       "INSERT INTO downloads VALUES ('{0}', '{1}', '{2}') " +
                                       "IF EXISTS(SELECT uniqueId FROM downloads WHERE uniqueID = '{0}') " +
                                       "Update downloads " +
                                       "set progress='{2}' " +
                                       "where uniqueId='{0}' ", uniqueId, fileName, e.BytesReceived);

    AsyncCallback callback = ((result) =>
    {
        sqlCommand.EndExecuteNonQuery(result);
        connection.Close();
    });

    sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
}

void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e, string uniqueId, string fileName)
{
    SqlConnection connection = new SqlConnection("Data Source=.\\SQLSERVER;Initial Catalog=XRingtoneDB;Integrated Security=True;Asynchronous Processing=true");
    connection.Open();
    SqlCommand sqlCommand = new SqlCommand();
    sqlCommand.Connection = connection;

    sqlCommand.CommandText = String.Format("update downloads " +
                                                "set progress='Completed' " +
                                                "where uniqueId='{0}' and fileName='{1}'", uniqueId, fileName);

    AsyncCallback callback = ((result) =>
    {
        sqlCommand.EndExecuteNonQuery(result);
        sqlCommand.Connection.Close();
    });
    sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
}

ProgressChanged工作正常,但DownloadCompleted僅在調試模式下工作。 我認為這是因為我需要超時或在這些調用之間等待。

Update3:有時我執行下載后在DB中有兩行相同的行! 困惑我是否需要關閉所有連接?

你可以使用AsyncCallback而不是Sleep()

AsyncCallback callback = new AsyncCallback(HandleCallback);
sqlcommand.BeginExecuteNonQuery(callback, sqlcommand);

使用回調處理異步狀態。

private void HandleCallback(IAsyncResult result)
{
  SqlCommand command = (SqlCommand)result.AsyncState;
  command.EndExecuteNonQuery(result);
  ....
}

更新2

但總體來說代碼是好的,您是否允許在一個唯一ID中下載多個文件? 如果您正在下載具有相同唯一ID的不同文件它可以更新報告不完整進度的下載表。

不確定你的意思DownloadCompleted只能在調試模式下工作,但你可以在WebMethod中使用私有變量來控制流。 說到這一點,由於您使用數據庫報告狀態已更改但未插入大量數據,因此您應考慮使用同步查詢,以便更好地歸檔結果。

您應該調用接受回調的BeginExecuteNonQuery的重載,並在回調結束時調用查詢。

更新

如果在數據庫執行完成后需要執行其他代碼,則需要在回調中啟動此代碼。

例如,如果您目前有:

sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);
DoSomeAdditionalWorkNow();

DoSomeAdditionalWorkNow不會等到查詢完成,如果它依賴於命令中更新的數據,您將遇到問題。

這可以通過將對額外工作方法的調用移動到回調中來解決:

AsyncCallback callback = ((result) =>
{
    sqlCommand.EndExecuteNonQuery(result);
    connection.Close();
    DoSomeAdditionalWorkNow();
});
sqlCommand.BeginExecuteNonQuery(callback, sqlCommand);

然而

我認為你的編程生活過於復雜。 您正在執行的查詢運行時間不長,您可以使用同步版本執行它們:

sqlCommand.ExecuteNonQuery();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM