2011-03-21 24 views
0

我將記錄拉出數據庫,將其內容發佈到事務性MSMQ隊列,然後更新行以指示它已發佈。 Enqueing-and-Updating是在TransactionScope中發生的,它本身在讀取所有記錄的DataReader-讀取循環內部。即:讀取發生在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(); 

使用,直到我修改GetUnpublishedEvents使用NOLOCK失敗,超時異常存儲過程SetEventAsPublished。我的問題是:這是一個好主意嗎?是否超時異常提示我應該以其他方式做這件事?

我知道NOLOCK在SQL Server中相當於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等價物。它針對閱讀進行了優化,但可以提升以允許在相同範圍內進行書寫。

只是一個評論,我認爲第二個連接是不必要的。此可能是是您超時的原因,因爲它會將您的事務升級爲使用DTC(單個事務中的兩個連接)。

+0

第二個連接是必需的,因爲第一個連接與打開的DataReader綁定。 – 2011-03-21 15:01:38

+1

您可以啓用MARS(多個活動結果集)來解決這個問題。 http://msdn.microsoft.com/en-us/library/yf1a7f4f(v=VS.80).aspx – 2011-03-21 15:28:37