Entity framework core EntityFrameworkCore Task.WhenAll()在上一个操作完成之前,在此上下文上启动了第二个操作

Entity framework core EntityFrameworkCore Task.WhenAll()在上一个操作完成之前,在此上下文上启动了第二个操作,entity-framework-core,asp.net-core-3.0,Entity Framework Core,Asp.net Core 3.0,我想从数据库中读取数据。为此,我创建了一个查询和queryhandler类 质问者 public class OrderGetQueryHandler: IQueryHandler<OrderGetQuery, OrderDTO> { private readonly GoodWillWebDbContext _context; private readonly IQueryDispatcher _queryDispatcher;

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

质问者

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();
        }
    }
公共类OrderGetQueryHandler:IQueryHandler { 私有只读GoodWillWebDbContext\u context; 专用只读IQueryDispatcher\u queryDispatcher; public OrderGetQueryHandler(GoodWillWebDbContext上下文,IQueryDispatcher queryDispatcher) { _上下文=上下文; _queryDispatcher=queryDispatcher; } 私人bool CheckPartnerBlock(BlockTypes blockType、十进制过期债务、bool支付) { if(blockType==BlockTypes.Block) 返回true; if(blockType==BlockTypes.NotBlock) 返回false; if(blockType==BlockTypes.PreiminaryPayment) 回报; 返回过期债务x.PaymentID).FirstOrDefaultAsync(x=>x.CustomerID==order.CustomerID); var getOrderLinesTask= _queryDispatcher.HandleAsync( 新OrderLinesGetQuery(query.OrderID)); 等待任务。whalll(getCustomerTask、getCuratorTask、getOrderLinesTask、getPaymentTask); var priceRange=wait_context.PriceRanges.FindAsync(getCustomerTask.Result.PriceRangeID); 将新订单返回到 ( order.OrderID, getCustomerTask.Result.Name, getOrderLinesTask.Result, order.CustomerID, order.OrderStateID, 坎德莱特勋章, 创建日期, getPaymentTask.Result.DebtBank, getPaymentTask.Result.Debt过期, this.CheckPartnerBlock(getCustomerTask.Result.BlockTypeID、getPaymentTask.Result.DebtOverside、order.PayOff), priceRange.Name, order.ReservationDate, Mapper.Convert(顺序) ); } 抛出新的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();
        });

    }
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
public void配置服务(IServiceCollection服务)
{
services.AddControllers();
字符串连接=配置.GetConnectionString(“DefaultConnection”);
services.AddDbContext(选项=>
options.UseSqlServer(连接),ServiceLifetime.Transient);
services.addScope();
services.addScope();
services.addScope();
services.addScope();
}
//此方法由运行时调用。请使用此方法配置HTTP请求管道。
public void配置(IApplicationBuilder应用程序、IWebHostEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(端点=>
{
endpoints.MapControllers();
});
}
}
我为我的上下文设置了ServiceLifetime.Transient,但仍然得到一个异常:InvalidOperationException在上一个操作完成之前在此上下文上启动的第二个操作


怎么了?

您似乎在上下文中运行多个操作,而不等待前面的操作结束,而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);

使这些呼叫同步或使用
wait
关键字

您似乎正在上下文上运行多个操作,而不等待前面的操作结束,而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);
使这些呼叫同步或使用
wait
关键字