带有DetachedLazyLoadingWarning的实体框架核心2.1问题

时间:2018-11-10 17:58:43

标签: c# entity-framework ef-code-first entity-framework-core code-first

我收到DetachedLazyLoadingWarning异常:

  

为警告“ Microsoft.EntityFrameworkCore.Infrastructure.DetachedLazyLoadingWarning”而生成的错误:尝试对类型为“ DeliveryProxy”的分离实体延迟加载导航属性“产品”。分离的实体或使用'AsNoTracking()'加载的实体不支持延迟加载。通过将事件ID'CoreEventId.DetachedLazyLoadingWarning'传递到'DbContext.OnConfiguring'或'AddDbContext'中的'ConfigureWarnings'方法,可以抑制或记录该异常。

尝试使用实体框架代码2.1

查询SQL数据库时

这是我的查询

var orders = 
    _context
    .Set<Order>()
    .Where(v => v.CompanyId == companyId)
    .Include(v => v.Details)
    .ThenInclude(d => d.Delivery)
    .ThenInclude(v => v.Product)
    .OrderByDescending(v=> v.Details.FirstOrDefault().Delivery.Product.ProductId)
    .ThenByDescending(v=> v.Details.FirstOrDefault().Delivery.Value)
    .ThenByDescending(v => v.CreatedAt)
    .Page(request.Page, request.RowsPerPage);

以下是实体和关系:

public class Order : IEntity<int>
{
    public int CompanyId { get; set; }

    public virtual ICollection<OrderDetails> Details { get; set; }

    [Required]
    public DateTimeOffset CreatedAt { get; set; }

    [Key]
    public int Id { get; set; }
}

public class OrderDetails : IEntity<int>
{
    public int OrderId { get; set; }

    public int DeliveryId { get; set; }

    [ForeignKey(nameof(OrderId))]
    public virtual Order Order { get; set; }

    [ForeignKey(nameof(DeliveryId))]
    public virtual Delivery Delivery { get; set; }

    [Key]
    public int Id { get; set; }
}

public class Delivery : IEntity<int>
{
    [Required]
    public int ProductId { get; set; }

    public int Value { get; set; }

    [ForeignKey(nameof(ProductId))]
    public virtual Product Product { get; set; }

    [Key]
    public int Id { get; set; }
}

[Table("Products")]
public class Product : IEntity<int>
{
    [Required]
    public byte ProductCategoryId { get; set; }


    public virtual ICollection<Delivery> Deliveries { get; set; }

    [Key]
    public int Id { get; set; }
}

类似Details.FirstOrDefault()分离实体Delivery。相同的解决方案可用于Entity Framework6。如何仅使用一个查询来改进查询以从数据库中获取日期(抑制警告无济于事)?

1 个答案:

答案 0 :(得分:2)

您还应该看到很多Client evaluation logging 警告。目前,客户评估在显式/延迟加载中效果不佳。

在这种情况下,导致客户评估的原因是订购方法中的v.Details.FirstOrDefault()表达式。 EF Core当前阶段面临的挑战是找到受支持的可翻译等效LINQ构造。

在这种特定情况下,解决方案(解决方法)是将中间SelectMany投影与Take(1)一起使用。用以下内容替换从.OrderByDescending(..)Page(...)的部分:

.SelectMany(
    o => o.Details.Select(d => d.Delivery).Take(1).DefaultIfEmpty(),
    (o, d) => new { Order = o, Delivery = d })
.OrderByDescending(v => v.Delivery.ProductId)
.ThenByDescending(v => v.Delivery.Value)
.ThenByDescending(v => v.Order.CreatedAt)
.Select(v => v.Order) // restore the original projection