Я извлекаю записи из базы данных, публикую их содержимое в очереди MSMQ для транзакций, затем обновляю строку, чтобы указать, что она была опубликована. Enqueing-and-Updating происходит внутри TransactionScope, который сам находится внутри цикла чтения DataReader, который проходит через все записи. То есть: чтение происходит за пределами TransactionScope. Примерно так:
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();
Хранимая процедура SetEventAsPublished
использовалась с ошибкой Timeout, пока я не изменил GetUnpublishedEvents
для использования NOLOCK
. Мой вопрос: это хорошая идея? Было ли исключение тайм-аута намеком на то, что я должен делать это другим способом?
Я знаю, что NOLOCK
эквивалентен в SQL Server READUNCOMMITTED
. Однако я не слишком беспокоюсь о том, чтобы читать непринятые данные в этом приложении (в первую очередь они не вставляются в транзакцию).
Edit:
Хранимые процедуры тривиальны. 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;