Подозирам, че не разбирам напълно какво се случва или се случва нещо странно. (Първият случай е по-вероятен според мен.)
Голямата картина:
- Опитвам се да накарам уеб услуга да изпълнява определени операции асинхронно, тъй като те могат да отнемат време и не искам клиентът да чака операциите да приключат (просто от време на време правете заявка за резултатите, за да видите операцията е Свършен).
- Асинхронният код е обвит в транзакция - в случай че нещо се обърка, искам да мога да върна всички промени назад.
- За съжаление последната стъпка от асинхронния код е да се извика РАЗЛИЧНА услуга, която отправя запитвания към същата база данни.
- Въпреки опаковането на цялото нещо в транзакция за моментна снимка, последната стъпка е неуспешна, тъй като услугата не може да чете от базата данни.
- По този въпрос, докато асинхронната операция е в ход, не мога да изпълня и прости оператори SELECT от базата данни.
Ето извадка от кода, който в момента използвам, за да тествам транзакциите (първо като използвам модела на Entity Framework 5):
using (var transaction = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.RequiresNew, new System.Transactions.TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.Snapshot }))
{
var db = new DataModelContainer();
Log test = new Log();
test.Message = "TEST";
test.Date = DateTime.UtcNow;
test.Details = "asd";
test.Type = "test";
test.StackTrace = "asd";
db.LogSet.Add(test);
db.SaveChanges();
using (var suppressed = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Suppress))
{
var newDb = new DataModelContainer();
var log = newDb.LogSet.ToArray(); //deadlock here... WHY?
}
test = db.LogSet.Where(l => l.Message == "TEST").Single();
db.LogSet.Remove(test);
db.SaveChanges();
transaction.Complete();
}
Кодът създава прост запис в дневника в базата данни (да, в момента си играя, така че стойностите са боклук). Настроих SQL базата данни да позволява изолиране на моментни снимки и доколкото ми е известно, четенията все още трябва да бъдат разрешени (те се тестват в този код чрез използване на нова, потисната транзакция и нов DataModelContainer
). Не мога обаче да направя заявка за LogSet
в потиснатата транзакция или в SQL Management Studio - цялата таблица е заключена!
Така че, защо? Защо е заключен, ако обхватът на транзакцията е дефиниран като такъв? Опитах и други нива на изолация (като ReadUncommited
) и все още не мога да направя запитване към таблицата.
Може ли някой да даде обяснение за това поведение?
Serializable
), катоReadUncommited
, а този дори не се нуждае от изолиране на моментни снимки, активирано на SQL сървъра! - person Shaamaan   schedule 24.01.2014