EF Core Include()在许多关系中

编程入门 行业动态 更新时间:2024-10-09 00:42:11
本文介绍了EF Core Include()在许多关系中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

$ b

使用EF Core,我们将这个关系与第三个实体的两个一对多关系分开: ProductCustomer

public partial class ProductCustomer { public long ProductId {get;组; } public long CustomerId {get;组; } public virtual Customer Customer {get;组; } public virtual Product Product {get;组; } public virtual ICollection< UsageRecord> UsageRecord {get;组; } }

UsageRecord 是包含某个客户在使用产品时使用的数据量

public partial class UsageRecord { public long Id {get;组; } public long ProductId {get;组; } public long CustomerId {get;组; } public decimal数量{get;组; } public virtual ProductCustomer ProductCustomer {get;组; } }

现在,如果我尝试阅读具体的 UsageRecord , ProductCustomer 对象是 null (完美,我正在使用热切的加载方式)

return _usageRecordEntity.Where(x => x.ProductId == productId).AsEnumerable();

但是,如果我特意要求Include()产品客户端实体,实体框架不仅包括所有递归引用,还包括 Product 对象和不是客户!

return _usageRecordEntity.Where(x => x.ProductId == productId ).Include(p => p.ProductCustomer).AsEnumerable();

第一件事:我不明白为什么它包括整个对象,如果我专门要求 ProductCustomer 一个。

第二件事:为什么产品而不是客户?!

我将包含完整性的上下文模型:

protected override void OnModelCreating(ModelBuilder modelBuilder ) { modelBuilder.Entity< Customer>(entity => { entity.Property(e => e.customerId) .IsRequired() .HasColumnName(CustomerId) .HasMaxLength(255); }); modelBuilder.Entity< Product>(entity => { entity.Property(e => e.Name) .IsRequired() .HasMaxLength(50); }); modelBuilder.Entity< ProductCustomer>(entity => { entity.HasKey(e => new {e.ProductId,e.CustomerId}) .HasName(PK__ProductCustomerComposite); entity.HasOne(d => d.Customer) .WithMany(p => p.ProductCustomer) .HasForeignKey (d => d.CustomerId) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName(FK__ProductCu__CustomerId); entity.HasOne(d => d。 .WithMany(p => p.ProductCustomer) .HasForeignKey(d => d.ProductId) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName FK__ProductCu__ProductId); }); modelBuilder.Entity< UsageRecord>(entity => { entity.Property(e => e.Quantity) .HasColumnType(decimal ) .HasDefaultValueSql(0); entity.HasOne(d => d.ProductCustomer) .WithMany(p => p.UsageRecord) .HasForeignKey(d => new {d.ProductId,d.CustomerId}) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName(FK_UsageRecordProductcustomer); }); }

解决方案

EF Core 部分中的提示 / core / querying / related-datarel =nofollow noreferrer>文档(突出显示是我的):

实体Framework Core将自动将导航属性修复到之前加载到上下文实例中的任何其他实体。 因此,即使您没有明确地包含导航属性的数据,如果先前加载了一些或所有相关实体,则该属性仍可能被填充。

The relation between Product and Customer is of type many-to-many (from a design point a view).

Using EF Core, we split this relation in two one-to-many relations with a third entity: ProductCustomer

public partial class ProductCustomer { public long ProductId { get; set; } public long CustomerId { get; set; } public virtual Customer Customer { get; set; } public virtual Product Product { get; set; } public virtual ICollection<UsageRecord> UsageRecord { get; set; } }

UsageRecord is a list of Records containing the quantity of data used by a certain customer while he is using a product

public partial class UsageRecord { public long Id { get; set; } public long ProductId { get; set; } public long CustomerId { get; set; } public decimal Quantity { get; set; } public virtual ProductCustomer ProductCustomer { get; set; } }

Now, if i try to read a specific UsageRecord, the ProductCustomer object is null (perfect, i am using an eager loading approach)

return _usageRecordEntity.Where(x => x.ProductId == productId).AsEnumerable();

But if i specifically ask to Include() the ProductCustomer entity, the entity framwork, not only includes all the recursive references but also includes the Product object and NOT the Customer!

return _usageRecordEntity.Where(x => x.ProductId == productId).Include(p => p.ProductCustomer).AsEnumerable();

First thing: I don't understand why it is including the whole chain of objects if i specifically ask just for the ProductCustomer one.

Second thing: Why the Product and NOT the Customer?!

I include for completeness the Context model:

protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Customer>(entity => { entity.Property(e => e.customerId) .IsRequired() .HasColumnName("CustomerId") .HasMaxLength(255); }); modelBuilder.Entity<Product>(entity => { entity.Property(e => e.Name) .IsRequired() .HasMaxLength(50); }); modelBuilder.Entity<ProductCustomer>(entity => { entity.HasKey(e => new { e.ProductId, e.CustomerId }) .HasName("PK__ProductCustomerComposite"); entity.HasOne(d => d.Customer) .WithMany(p => p.ProductCustomer) .HasForeignKey(d => d.CustomerId) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName("FK__ProductCu__CustomerId"); entity.HasOne(d => d.Product) .WithMany(p => p.ProductCustomer) .HasForeignKey(d => d.ProductId) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName("FK__ProductCu__ProductId"); }); modelBuilder.Entity<UsageRecord>(entity => { entity.Property(e => e.Quantity) .HasColumnType("decimal") .HasDefaultValueSql("0"); entity.HasOne(d => d.ProductCustomer) .WithMany(p => p.UsageRecord) .HasForeignKey(d => new { d.ProductId, d.CustomerId }) .OnDelete(DeleteBehavior.Restrict) .HasConstraintName("FK_UsageRecordProductcustomer"); }); }

解决方案

Basically the answer is provided by the following Tip in the Loading Related Data - Eager loading section of the EF Core documentation (highlight is mine):

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

更多推荐

EF Core Include()在许多关系中

本文发布于:2023-11-15 06:25:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1591939.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:关系   EF   Core   Include

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!