У меня есть класс UoW, который имеет начало и фиксацию, как показано ниже

public class uow
{
    private IDBcontext mydbcontext;
    TransactionScope trans = null;

    public uow(IDBConext mydbcontext)
    {
        this.mydbcontext = mydbcontext;
    }

    public void starttran()
    {
       if (trans == null)
           trans = new TransactionScope(TransactionScopeAsyncFlowOption.enabled);
    }

    public async task Commit()
    {
       var mydb = mydbcontext as IObjectContextAdapter;
       if (mydb != null)
          await mydb.ObjextContext.SaveChangesAsync(SaveOptions.DetectChangesBeforeSave);

       if (trans!=null)
       {
           trans.Complete();
           trans = new TransactionScope();
       }

       mydb.ObjectContext.AcceptAllChanges();
   }
}

Теперь в своей реализации я вставляю 2 записи в 2 разные таблицы и получаю значения ключей обратно. Затем я выполняю еще одну вставку в третью таблицу с этими двумя ключами.

Если вторая или третья вставка не удалась, мне нужно иметь возможность откатить первую или первые две вставки (все вставки должны быть успешными или все должны потерпеть неудачу).

Table1 tab1 = new Table1();
Table2 tab2 = new Table2();
Table3 tab3 = new Table3();

UOW uw = new UOW(mydbcontext);
uw.Starttran();

tab1.createdby = "user1";
tab1.name = "name";

tab1 = mydbcontext.Table1.Add(tab1);
await mydbcontext.SaveChangesAsync();

tab2.createdby = "user1";
tab2.name = "name";

tab2 = mydbcontext.Table2.Add(tab2);
await mydbcontext.SaveChangesAsync();

tab3.table1Id = tab1.Id;
tab3.table2Id = tab2.Id;

tab3 = mydbcontext.Table3.Add(tab3);
await mydbcontext.SaveChangesAsync();

if(tab3.Id > 0)
  await uow.Commit();
else
  await uow.RollBack();

Моя проблема: транзакция не фиксируется. Когда я отлаживаю, я вижу, что значение tab3.Id создано правильно, и оно действительно. Но когда я запрашиваю свою таблицу SQL Server, она показывает блокировку и не возвращает никаких результатов запроса. Когда я вручную закрываю сеанс отладки, блокировки нет, но новая запись не существует / не вставлена.

Что я здесь не так делаю? Прочитал несколько обсуждений здесь и не нашел ответа ..

Ответы (1)

The commit method returns an awaitable Task, so because the call is not awaited, the program may continue to run and even finish before the call is completed. In the last part of your implementation yo should do:

if(tab3.Id > 0)
  await uow.Commit();
else
  await uow.RollBack();  // Assuming that this one is also an async method

Хорошей практикой является добавление префикса Async к методам, поддерживающим async-await.

Также, но не связанного с проблемой, когда вы фиксируете транзакцию, почему вы создаете новую область транзакции? Это не кажется необходимым, и, согласно определению шаблона единицы работы, единицу работы не следует повторно использовать после того, как изменения будут зафиксированы.

if (trans!=null)
{
  trans.Complete();
  trans = new TransactionScope(); // ???
}

2022 WebDevInsider