Async / await ile çalışmak için TransactionScope'u edinin


114

Servis otobüsümüze async/ awaitiçine entegre etmeye çalışıyorum . SingleThreadSynchronizationContextBu örneğe göre http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx uyguladım .

Ve bir şey hariç, cezası çalışır: TransactionScope. İçerideki şeyleri bekliyorum TransactionScopeve TransactionScope.

TransactionScopeasync/ ile iyi oynamış gibi görünmüyor await, çünkü kullanarak iş parçacığındaki şeyleri depoladığı için ThreadStaticAttribute. Bu istisnayı anlıyorum:

"TransactionScope yanlış şekilde iç içe geçmiş.".

TransactionScopeGörevi sıraya koymadan önce verileri kaydetmeyi ve çalıştırmadan önce geri yüklemeyi denedim, ancak hiçbir şeyi değiştirmiyor gibi görünüyor. Ve TransactionScopekod tam bir karmaşa, bu yüzden orada neler olduğunu anlamak gerçekten zor.

Çalışmasını sağlamanın bir yolu var mı? Alternatif var mı TransactionScope?


İşte bir TransactionScope hatasını yeniden oluşturmak için çok basit bir kod pastebin.com/Eh1dxG4a, ancak buradaki istisna Transaction Aborted
Yann

Normal bir SQL işlemi kullanabilir misiniz? Yoksa birden fazla kaynağı mı kapsıyorsunuz?
Marc Gravell

Birden fazla kaynağı kapsıyorum
Yann

Görünüşe göre ya kapsamı zaman uyumsuz yönteminize aktarmanız ya da onu çalışma biriminizle tanımlanan bir tür ortak bağlamdan almanın bir yolunu vermeniz gerekecek.
Bertrand Le Roy

SingleThreadSynchronizationContextHer üst düzey için ayrı bir ileti dizisine ihtiyacınız olacak TransactionScope.
Stephen Cleary

Yanıtlar:


161

.NET Framework 4.5.1'de, parametre alan bir dizi yeni oluşturucuTransactionScope vardır TransactionScopeAsyncFlowOption.

MSDN'ye göre, iş parçacığı sürekliliği boyunca işlem akışını sağlar.

Anladığım kadarıyla şu şekilde kod yazmanıza izin veriyor:

// transaction scope
using (var scope = new TransactionScope(... ,
  TransactionScopeAsyncFlowOption.Enabled))
{
  // connection
  using (var connection = new SqlConnection(_connectionString))
  {
    // open connection asynchronously
    await connection.OpenAsync();

    using (var command = connection.CreateCommand())
    {
      command.CommandText = ...;

      // run command asynchronously
      using (var dataReader = await command.ExecuteReaderAsync())
      {
        while (dataReader.Read())
        {
          ...
        }
      }
    }
  }
  scope.Complete();
}

10

Bir cevap için biraz geç ama MVC4 ile aynı sorunu yaşıyordum ve projeye sağ tıklayarak mülklere git seçeneğine tıklayarak projemi 4.5'ten 4.5.1'e güncelledim. Uygulama sekmesini seçin, hedef çerçeveyi 4.5.1 olarak değiştirin ve işlemi aşağıdaki gibi kullanın.

using (AccountServiceClient client = new AccountServiceClient())
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
}


6

Transaction.DependentClone () yöntemi tarafından oluşturulan DependentTransaction'ı kullanabilirsiniz :

static void Main(string[] args)
{
  // ...

  for (int i = 0; i < 10; i++)
  {

    var dtx = Transaction.Current.DependentClone(
        DependentCloneOption.BlockCommitUntilComplete);

    tasks[i] = TestStuff(dtx);
  }

  //...
}


static async Task TestStuff(DependentTransaction dtx)
{
    using (var ts = new TransactionScope(dtx))
    {
        // do transactional stuff

        ts.Complete();
    }
    dtx.Complete();
}

DependentTransaction ile Eş Zamanlılığı Yönetme

http://adamprescott.net/2012/10/04/transactionscope-in-multi-threaded-applications/


2
Adam Prescott'un örnek çocuk görevi eşzamansız olarak işaretlenmedi. "İşlemsel şeyler yap" ı await Task.Delay(500)bu kalıp gibi bir şeyle değiştirirseniz TransactionScope nested incorrectly, en dıştaki TransactionScope (yukarıdaki örnekte gösterilmemiştir) alt görev düzgün şekilde tamamlanmadan kapsamdan çıktığı için de başarısız olur . değiştirmekawait ile Task.Wait()ve işe yarıyor, ama sonra faydalarını kaybettim async.
mdisibio

Bu, sorunu çözmenin daha zor bir yoludur. TransactionScope, tüm bu tesisat işlerini gizlemek içindir.
Eniola
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.