2011-03-21 9 views
0

レコードをデータベースから取り出し、その内容をトランザクション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; 

答えて

1

あなたは、テーブル内の行を照会し、同じトランザクション内でそれらを更新していますか?それがテーブルにぶつかる唯一の場所である限り(たとえ他の誰かが未発表のイベントを入れても、それはあなたに影響しません))、私はこのようにしても何の問題も見ません。

基本的に、ReaderWriterLockに相当するSQLを実行しています。これは読み込み用に最適化されていますが、同じスコープ内で書き込みができるように昇格することができます。

ただ1つのコメント、私は2番目の接続が不要だと思います。このは、DTC(1つのトランザクションで2つの接続)を使用するようにトランザクションをエスカレートするため、タイムアウトの原因になります。

+0

最初の接続が開いているDataReaderと結びついているため、2番目の接続が必要です。 –

+1

MARS(Multiple Active Result Sets)を有効にして回避することができます。 http://msdn.microsoft.com/en-us/library/yf1a7f4f(v=VS.80).aspx –

関連する問題