【问题标题】:EntityFrameworkCore Task.WhenAll() A second operation started on this context before a previous operation completedEntityFrameworkCore Task.WhenAll() 在前一个操作完成之前在此上下文上启动了第二个操作
【发布时间】:2020-03-13 08:28:49
【问题描述】:

我想从数据库中读取数据。为此,我创建了一个查询和查询处理程序类

查询处理程序

public class OrderGetQueryHandler: IQueryHandler<OrderGetQuery, OrderDTO>
    {
        private readonly GoodWillWebDbContext _context;
        private readonly IQueryDispatcher _queryDispatcher;

        public OrderGetQueryHandler(GoodWillWebDbContext context, IQueryDispatcher queryDispatcher)
        {
            _context = context;
            _queryDispatcher = queryDispatcher;
        }

        private bool CheckPartnerBlock(BlockTypes blockType, decimal debtOverdue, bool payOff)
        {
            if (blockType == BlockTypes.Block)
                return true;
            if (blockType == BlockTypes.NotBlock)
                return false;
            if (blockType == BlockTypes.PreliminaryPayment)
                return payOff;

            return debtOverdue <= 0;
        }

        public async Task<OrderDTO> HandleAsync(OrderGetQuery query)
        {
            var order = await _context.Orders.FindAsync(query.OrderID);
            if (order != null)
            {
                var getCustomerTask = _context.Partners.FindAsync(order.CustomerID).AsTask();
                var getCuratorTask = _context.Users.FindAsync(order.CuratorID).AsTask();
                var getPaymentTask = _context.Payments.OrderByDescending(x => x.PaymentID).FirstOrDefaultAsync(x => x.CustomerID == order.CustomerID);
                var getOrderLinesTask =
                    _queryDispatcher.HandleAsync<OrderLinesGetQuery, OrderLineDTO[]>(
                        new OrderLinesGetQuery(query.OrderID));

                await Task.WhenAll(getCustomerTask, getCuratorTask, getOrderLinesTask, getPaymentTask);

                var priceRange = await _context.PriceRanges.FindAsync(getCustomerTask.Result.PriceRangeID);
                return new OrderDTO
                    (
                        order.OrderID,
                        getCustomerTask.Result.Name,
                        getOrderLinesTask.Result,
                        order.CustomerID,
                        order.OrderStateID,
                        order.CanDelete,
                        order.CreationDate,
                        getPaymentTask.Result.DebtBank,
                        getPaymentTask.Result.DebtOverdue,
                        this.CheckPartnerBlock(getCustomerTask.Result.BlockTypeID, getPaymentTask.Result.DebtOverdue, order.PayOff),
                        priceRange.Name,
                        order.ReservationDate,
                        Mapper.Convert<DeliveryInfoDTO, BaseEntities.Entities.Sales.Order>(order)
                    );
            }
            throw new NullReferenceException();
        }
    }

我在 ASP.NET WEB 应用程序中使用的这个查询处理程序。我的创业班是

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        string connection = Configuration.GetConnectionString("DefaultConnection");

        services.AddDbContext<GoodWillWebDbContext>(options =>
            options.UseSqlServer(connection), ServiceLifetime.Transient);

        services.AddScoped<IQueryHandler<OrdersGetQuery, BaseEntities.DTO.Sales.Order.OrderDTO[]>, OrdersGetQueryHandler>();
        services.AddScoped<IQueryHandler<OrderGetQuery, Sales.Queries.DTO.Order.OrderDTO>, OrderGetQueryHandler>();

        services.AddScoped<ICommandDispatcher, CommandDispatcher>();
        services.AddScoped<IQueryDispatcher, QueryDispatcher>();

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

    }
}

我为我的上下文设置了 ServiceLifetime.Transient,但我仍然遇到异常:InvalidOperationException A second operation started on this context before an previous operation complete.

怎么了?

【问题讨论】:

    标签: entity-framework-core asp.net-core-3.0


    【解决方案1】:

    您似乎正在上下文中运行多个操作,而无需等待前一个操作结束,而 EF 不喜欢:

    var getCustomerTask = _context.Partners.FindAsync(order.CustomerID).AsTask();
    var getCuratorTask = _context.Users.FindAsync(order.CuratorID).AsTask();
    var getPaymentTask = _context.Payments.OrderByDescending(x => x.PaymentID).FirstOrDefaultAsync(x => x.CustomerID == order.CustomerID);
    

    要么使这些调用同步,要么使用await 关键字。

    【讨论】:

      猜你喜欢
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2020-01-22
      • 1970-01-01
      • 2018-11-07
      • 2021-10-22
      • 2017-03-14
      相关资源
      最近更新 更多