Exemplo n.º 1
0
        public async virtual Task <int> AddItems(params Item[] items)
        {
            _ctx.Items.AddRange(items);
            var transaction = new AppTransaction();

            _ctx.Transactions.Add(transaction);
            int result   = 0;
            var strategy = _ctx.Database.CreateExecutionStrategy();

            try
            {
                Debug.WriteLine(_ctx.Entry(transaction).State);//Added
                strategy.ExecuteInTransaction(
                    operation: () =>
                {
                    result = _ctx.SaveChanges();
                    throw new ConnectionAbortedException();
                },
                    verifySucceeded: () => _ctx.Transactions.AsNoTracking().Any(t => t.Id == transaction.Id)
                    );
            }catch (Exception ex)
            {
                Debug.WriteLine(_ctx.Entry(transaction).State);//Unchanged
            }
            return(result);
        }
Exemplo n.º 2
0
 public RatesController(
     AppTransaction tx,
     IMapper mapper,
     RateRepository rateRepository,
     BoardGameRepository boardGameRepository,
     UserManager <User> userManager
     )
 {
     TX                   = tx;
     _mapper              = mapper;
     _rateRepository      = rateRepository;
     _userManager         = userManager;
     _boardGameRepository = boardGameRepository;
 }
Exemplo n.º 3
0
        public async virtual Task <Item> AddItem(Item item)
        {
            //using (var transaction = new TransactionScope()) //Ошибка при выбранной стратегии устойчевого выполнения
            //{
            //    await _ctx.Items.AddAsync(item);
            //    await _ctx.SaveChangesAsync();
            //    transaction.Complete();
            //}


            var strategy = _ctx.Database.CreateExecutionStrategy(); //Можно создать без opt => opt.EnableRetryOnFailure() в конфигурцаии UseSqlServer
            //Решение 1
            //Но не учтена ошибка при фиксации транзакции (напр. прерывание соединения, а данные уже сохранены в бд)
            //await strategy.Execute(async () =>
            //{
            //    using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            //    {
            //        await _ctx.Items.AddAsync(item);
            //        await _ctx.SaveChangesAsync();
            //        //Здесь поток уже может быть другим
            //        transaction.Complete();
            //    }
            //});


            //Решение 2 без явного вызова транзакции и с проверкой достоврености транзакции
            //Этот вызов можно включить в переопределение метода SaveChanges контекста
            AppTransaction transaction = new AppTransaction();
            await _ctx.Items.AddAsync(item);

            await _ctx.Transactions.AddAsync(transaction);

            strategy.ExecuteInTransaction(_ctx,
                                          operation: (context) =>
            {
                context.SaveChanges(acceptAllChangesOnSuccess: false); //ChangeTracking не участвует в откате транзакции
            },
                                          verifySucceeded: context =>  //Вызывается в случае определенной ошибки в первом делегате. Может быть не вызван
            {
                //Если false - можно описать логику возвращения состояния контекста до очередного запуска транзакции
                return(context.Transactions.AsNoTracking().Any(t => t.Id == transaction.Id));
            });
            //Если выполнения дойдет сюда - значит все сохранено успешно
            _ctx.ChangeTracker.AcceptAllChanges();
            _ctx.Transactions.Remove(transaction);
            _ctx.SaveChanges();

            return(item);
        }