实体框架核心乐观并发

时间:2019-10-21 11:31:10

标签: ado.net entity-framework-core cqrs optimistic-locking

我正在研究应用CQRS的库存微服务。我们有一个储备库,可以使用特定的reservationId进行保留。因此1个StockLine可能只有1个具有相同保留ID的保留。如果进行了2个具有相同ReservationId的预订,则该预订的预订数量会增加。在阅读方面,尽管我应该在同一张表中显示可用的库存行+所有保留作为单独的行:   enter image description here

现在,我为读取模型实现了乐观并发。而且效果很好。查看代码:

public class Handler
    {
        public async Task Handle(StockReserved @event)
        {
            var optionsBuilder = new DbContextOptionsBuilder<StockLinesDbContext>();

            optionsBuilder.UseSqlServer("Data Source=localhost;Initial Catalog=DBName;Integrated Security=True;");

            using (var context = new StockLinesDbContext(optionsBuilder.Options))
            {
                var available = context.StockLines.Single(p => !p.IsReserved);
                var existingReservation = context.StockLines.SingleOrDefault(p => p.Id == @event.ReservationId);

                if (existingReservation != null)
                {
                    existingReservation.Quantity += @event.Amount;
                }
                else
                {
                    var res = new StockLine
                    {
                        Id = Guid.NewGuid(),
                        Quantity = @event.Amount,
                        IsReserved = true,
                        ReservationId = @event.ReservationId,
                        Product = "coke"
                    };
                    context.StockLines.Add(res);
                }

                available.Quantity -= @event.Amount;

                var saved = false;
                while (!saved)
                {
                    try
                    {
                        await context.SaveChangesAsync();
                        saved = true;
                    }
                    catch (DbUpdateConcurrencyException ex)
                    {
                        foreach (var entry in ex.Entries)
                        {

                            if (entry.Entity is StockLine && !((StockLine)entry.Entity).IsReserved)
                            {
                                var proposedValues = entry.CurrentValues;
                                var databaseValues = (StockLine)entry.GetDatabaseValues().ToObject();

                                ((StockLine)entry.Entity).Quantity = databaseValues.Quantity - @event.Amount;

                                // Refresh original values to bypass next concurrency check
                                entry.OriginalValues.SetValues(databaseValues);
                            }
                            if (entry.Entity is StockLine && ((StockLine)entry.Entity).IsReserved)
                            {
                                var proposedValues = entry.CurrentValues;
                                var databaseValues = (StockLine)entry.GetDatabaseValues().ToObject();


                                ((StockLine)entry.Entity).Quantity = databaseValues.Quantity + @event.Amount;

                                // Refresh original values to bypass next concurrency check
                                entry.OriginalValues.SetValues(databaseValues);
                            }
                        }
                    }
                }
            }
        }
    }

现在,我为该处理程序添加了幂等支持。这个想法是在同一事务中尝试将eventId添加到单独的表中,如果该插入失败,则意味着该事件已被处理。

using (var transaction = connection.BeginTransaction())
            {
                // Run raw ADO.NET command in the transaction
                var command = connection.CreateCommand();
                command.Transaction = transaction;
                command.CommandText =
                    $"Insert INTO dbo.ReadModel_Idempotency VALUES ('{ReadModelName}', '{@event.EventId}')";

                try
                {
                    command.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"FAILED TO INSERT: {@event.EventId}");
                    return;
                }

添加了Idempotency支持后,乐观并发无法按需工作,仍然存在许多不一致数据。 完整的代码可以在这里找到:https://github.com/dmitribodiu/OptimisticConcurrencyTest 我添加幂等实现后为何不起作用呢?

0 个答案:

没有答案