Я хотел бы использовать оптимистичный параллелизм с TransactionScope
. Вот код, который я придумал до сих пор:TransactionScope и оптимистический параллелизм
var options = new TransactionOptions {IsolationLevel = IsolationLevel.ReadCommitted};
using (var scope = new TransactionScope(TransactionScopeOption.Required, options))
{
using (var connection = new SqlConnection(_connectionString))
{
// ... execute some sql code here
// bump up version
var version = connection.ExecuteScalar<DateTime>(@"
DECLARE @version datetime2 = SYSUTCDATETIME();
UPDATE [Something].[Test]
SET [Version] = @version
WHERE Id = @Id
SELECT @version
", new {Id = id});
// ... execute more sql code here
// check if version has not changed since bump up
// NOTE: version is global for the whole application, not per row basis
var newVersion = connection.ExecuteScalar<DateTime>("SELECT MAX([Version]) FROM [Something].[Test]");
if (newVersion == version) scope.Complete(); // looks fine, mark as completed
}
} // what about changes between scope.Complete() and this line?
К сожалению, этот код вызывает серьезную проблему. Между проверкой версии и фиксацией транзакции могут быть некоторые изменения в базе данных. Это стандартная ошибка time of check to time of use. Единственный способ, с помощью которого я могу это решить, - выполнить проверку версии и совершить транзакцию как одну команду.
Возможно ли выполнить некоторый код SQL вместе с фиксацией транзакции с использованием TransactionScope
? Если нет, то какое другое решение можно использовать?
EDIT1: Версия должна быть за приложение, а не за строку.
EDIT2: Я мог бы использовать сериализуемый уровень изоляции, но это не вариант из-за проблем с производительностью, которые могут возникнуть.
Кажется, что самым простым решением было бы переместить весь этот код sql в хранимую процедуру и поместить его в транзакцию. Честное продвижение sql из вашего приложения - хорошая идея в любом случае создать многоуровневую архитектуру и отделить код от реализации данных. –
@SeanLange Это изменение должно быть выполнено на уже существующей системе, и перемещение всей логики в хранимые процедуры не является вариантом. –