[英]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個事件( ProgressChanged
和DownloadCompleted
)
[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.