レコードをデータベースから取り出し、その内容をトランザクションMSMQキューにパブリッシュし、その行がパブリッシュされたことを示すように更新しています。 Enqueing-and-Updatingは、すべてのレコードを処理するDataReader読み取りループ内にあるTransactionScope内で実行されます。つまり、TransactionScopeのの外側にある読み取りがです。このような何か:NOLOCKを使用してクエリ/更新シナリオを回避することをお勧めしますか?
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "GetUnpublishedEvents";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection
| System.Data.CommandBehavior.SingleResult);
while (reader.Read())
using (TransactionScope scope = new TransactionScope())
{
string ID = reader.GetString(0);
string data = reader.GetString(1);
SqlConnection updateConn = new SqlConnection(ConnectionString);
updateConn.Open();
SqlCommand updateCommand = updateConn.CreateCommand();
updateCommand.CommandText = "SetEventAsPublished";
updateCommand.CommandType = System.Data.CommandType.StoredProcedure;
updateCommand.Parameters.Add(new SqlParameter("@ID", ID));
updateCommand.ExecuteNonQuery();
updateConn.Close();
Message msg = new Message(data);
RaiseMessageArrived(msg);
scope.Complete();
}
reader.Close();
私はNOLOCK
を使用するようにGetUnpublishedEvents
を修正するまで、タイムアウト例外で失敗するために使用するストアドプロシージャSetEventAsPublished
。私の質問です:これは良い考えですか?タイムアウトの例外は私がこれを他のやり方でやっているべきであるというヒントでしたか?
NOLOCK
は、SQLサーバーでREADUNCOMMITTED
と同等です。私はこのアプリケーションでコミットされていないデータを読むことについてあまり心配していませんが(最初はトランザクションに挿入されません)。
編集:
ストアドプロシージャはどちらも簡単です。 GetUnpublishedEvents
だけです:
SELECT id, data
FROM eventsTable WITH (NOLOCK)
WHERE data IS NOT NULL
AND published IS NULL;
SetEventAsPublished
ですが:
UPDATE eventsTable
SET published = GETDATE()
WHERE ID = @ID;
最初の接続が開いているDataReaderと結びついているため、2番目の接続が必要です。 –
MARS(Multiple Active Result Sets)を有効にして回避することができます。 http://msdn.microsoft.com/en-us/library/yf1a7f4f(v=VS.80).aspx –