EF Core Include()在许多关系中 [英] EF Core Include() in Many to Many relation
问题描述
$ b 使用EF Core,我们将这个关系与第三个实体的两个一对多关系分开: ProductCustomer UsageRecord 是包含某个客户在使用产品时使用的数据量 现在,如果我尝试阅读具体的 UsageRecord , ProductCustomer 对象是 null (完美,我正在使用热切的加载方式) 但是,如果我特意要求Include()产品客户端实体,实体框架不仅包括所有递归引用,还包括 Product 对象和不是客户! 第一件事:我不明白为什么它包括整个对象 第二件事:为什么产品而不是客户
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;组; }
}
public partial class UsageRecord
{
public long Id {get;组; }
public long ProductId {get;组; }
public long CustomerId {get;组; }
public decimal数量{get;组; }
public virtual ProductCustomer ProductCustomer {get;组; }
}
return _usageRecordEntity.Where(x => x.ProductId == productId).AsEnumerable();
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()在许多关系中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!