【问题标题】:EF Core 3.0 MoveNext Error when Include using SingleOrDefault包含使用 SingleOrDefault 时的 EF Core 3.0 MoveNext 错误
【发布时间】:2020-05-14 19:04:54
【问题描述】:

我阅读了不同的解决方案并尝试了不同的实现,但没有任何结果。 使用不同的实现,错误总是相同的:“System.InvalidOperationException: Enumerator failed to MoveNextAsync.”

这是产生异常的地方。

var portfolioTrades = await _context
      .Portfolios
      .Include(PortfolioEntityTypeConfiguration.TradesList)
      .SingleOrDefaultAsync(x => x.id == id);

包含的处理方式

  builder.OwnsMany<Trade>(TradesList, x =>
            {
                x.WithOwner().HasForeignKey("portfolio_id");
                x.ToTable("product_trade", SchemaNames.Public);

                x.Property<TradeID>("id");
                x.Property<DateTimeOffset>("_date").HasColumnName("date");
                x.Property("_details").HasColumnName("details");
                x.Property<Guid>("_schemaId").HasColumnName("schema_id");

                x.HasKey(x => x.id);

            });

EF 执行此查询并返回 1 条记录

SELECT t.id, t.description, t.end_client_name, t.name, t0.id, t0.details, t0.portfolio_id
FROM (
    SELECT p.id, p.description, p.end_client_name, p.name
    FROM account.portfolio AS p
    WHERE p.id = '3adcaff1-de64-4ae3-b8b7-c390d76aa0bd'
    LIMIT 2
) AS t
LEFT JOIN product_trade AS t0 ON t.id = t0.portfolio_id
ORDER BY t.id, t0.id

这里是实体

 public class Trade : Entity
{
    public TradeID id { get; private set; }

    private DateTimeOffset _date { get; set; }

    public JObject _details { get; set; }

    private Guid _schemaId { get; set; }

    private Trade()
    {
        id = new TradeID(Guid.NewGuid());
    }

    private Trade( DateTimeOffset date, string details, Guid schema_id)
    {
        id = new TradeID(Guid.NewGuid());
        _date = date;
        _schemaId = schema_id;
        _details = JsonConvert.DeserializeObject<JObject>(details);
    }

    internal static Trade Create(DateTimeOffset date, string details, Guid schema_id)
    {
        return new Trade(date, details, schema_id);
    }

}

}

public class Portfolio : Entity, IAggregateRoot
{
    public PortfolioID id { get; private set; }

    private string _name { get; set; }

    private string _end_client_name { get; set; }

    private string _description { get; set; }

    private readonly List<Trade> _trades;

    private Portfolio()
    {
       _trades = new List<Trade>();
    }
}

// 错误

System.InvalidOperationException: Enumerator failed to MoveNextAsync.
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Rx.Products.Infrastructure.Domain.Portfolios.PortfolioRepository.GetByPortfolioIdAsync(PortfolioID id) in ....\PortfolioRepository.cs:line 37
   at Rx.Products.Application.Portfolios.CreateTrade.CreateTradeCommandHandler.Handle(CreateTradeCommand request, CancellationToken cancellationToken) in ...\CreateTradeCommandHandler.cs:line 19
   at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at Rx.Products.API.TradesController.RegisterCustomer(CreateTradeRequest new_trade) in ....\TradesController.cs:line 65
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 726
Content-Type: application/json
Host: localhost:54315
User-Agent: PostmanRuntime/7.24.1
Postman-Token: 2aabfa69-9d5c-4637-9d48-02a713077235

ms guide about relation 产生同样的错误。 感谢您的宝贵时间。

【问题讨论】:

  • 异常中有更多信息吗?请问可以添加stacktrace吗?
  • @GuruStron ,当然,我添加了它。 tnx
  • @GuruStron 只是为您提供更多详细信息。如果我删除包含代码正常工作并且实体已填充。
  • 似乎出于某种原因 EF 获得了多条记录。试试FirstOrDefaultAsyncSingleOrDefault。请参阅thisthis 问题。
  • @GuruStron 与 SingleOrDefault 查询更改,将 LIMIT 修改为 1 但返回的错误是相同的。感谢您提供的链接是我阅读的一些文章,但没有任何结果:/

标签: c# ef-core-3.0


【解决方案1】:
  1. 我认为拥有一个可用于导航并定义Portfolio 类和Trade 类之间关系的公共Portfolio.Trades 属性真的会帮助您。
    public class Portfolio : Entity, IAggregateRoot
    {
        // Other class members defined above...

        // New public navigation property for the relationship.
        public IReadOnlyList<Trade> Trades => _trades.AsReadOnly();
    }
  1. 如果使用OwnsMany 关系,则不需要在查询中使用.Include 语句。如果您使用HasMany 关系,则需要使用.Include 语句。

使用HasManyInclude

builder.HasMany(port.Trades, x =>
            {
                // Other configuration code defined above...
            });

var portfolioTrades = await _context
      .Portfolios
      .Include(port => port.Trades)
      .SingleOrDefaultAsync(port => port.id == id);

使用OwnsMany 而不是Include

builder.OwnsMany(port.Trades, x =>
            {
                // Other configuration code defined above...
            });

var portfolioTrades = await _context
      .Portfolios
      .SingleOrDefaultAsync(port => port.id == id);

使用OwnsMany 关系意味着将自动为您查询所有Trade 子对象。使用HasMany 关系允许您指定包含子Trade 对象作为查询的一部分。

【讨论】:

  • 请史蒂夫支持。修改实体投资组合有 y 建议我有一个新错误。 ---> 类型“贸易”不能标记为自有,因为已经存在同名的非自有实体类型。
  • 显然我使用 OwnsMany 删除了“包含”
  • 如果Portfolio 之外的其他实体与Trade 实体有关系,则Trade 实体不能归Portfolio 实体所有。解决该错误的最简单方法是使用HasMany 关系并在查询中使用.Include 语句。我喜欢使用OwnsMany 关系,其中子项的数量相对“少”,并且子项的集合不会无限制地增长。您可以在此处阅读有关差异的更多信息:stackoverflow.com/questions/58516830/…
  • builder.OwnsMany(ProductIdentifiers, i =>{ ..... });我使用了您向我建议的代码,但错误仍然相同。使用 var product = await _context .Products .Where(x => x.Id == id).SingleAsync(); 调用实体并且错误始终是相同的 Enumerator failed to MoveNextAsync。谢谢马西莫
  • .Products.Where(x => x.Id == id).ToListAsync();使用此语句,如果在 sql 工具中执行,则生成的查询可以正确运行但 vs 冻结...
猜你喜欢
  • 2020-03-08
  • 2020-02-24
  • 1970-01-01
  • 2019-03-14
  • 2021-07-12
  • 2021-12-21
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多