【问题标题】:EF POCO table splitting: both entities loadEF POCO 表拆分:两个实体都加载
【发布时间】:2013-05-20 12:49:08
【问题描述】:

抱歉,我对表格拆分感到困惑!

我有 Product 和 ProductDetail 实体,映射到表 Product。

当我加载 Products 集合时,也会加载 ProductDetails。

有人能解释一下我如何防止 ProductDetails 被加载,直到我真的想要它们吗?谢谢!

        using (var ctx = new Context(cs))
        {
            var pc = ctx.Products.Local.Count();
            var pdc = ctx.ProductDetails.Local.Count();
            Assert.IsTrue(pc == 0);
            Assert.IsTrue(pdc == 0);

            ctx.Products.Load();

            pc = ctx.Products.Local.Count();
            pdc = ctx.ProductDetails.Local.Count();
            Assert.IsTrue(pc >= 10); //OK so far
            Assert.IsTrue(pdc == 0); //no, they are all there

        }

我的上下文类和实体:

public class Context:DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }

    public Context():base()
    {            
    }

    public Context(string nameOrConnectionString) : base(nameOrConnectionString)
    {

    }

    public DbSet<Product> Products { get; set; }
    public DbSet<ProductDetail> ProductDetails { get; set; }

}

[Table("Product")]
public class Product
{
    [Key]
    public virtual int ProductId { get; set; }
    public virtual string Name { get; set; }
}

[Table("Product")]    
public class ProductDetail:Product
{
    //[Key]
    //public virtual int ProductId { get; set; }
    //public virtual string Name { get; set; }
    public virtual string Description { get; set; }
}

【问题讨论】:

    标签: .net entity-framework poco


    【解决方案1】:

    发生这种情况的原因是因为您有 ProductDetail 继承自 Product,这在技术上使其成为 Table-per-Hierarchy mapping 而不是简单的表拆分。这意味着,每当您加载所有Products 时,您也必然会加载所有ProductDetails。 EF 知道如何区分这两者,因此在加载每个实体时,框架会将其分类到您上下文中的正确 DbSet 中——它们都被添加到 Products 集合中,但有些也被添加到 @ 987654328@也设置好了。

    幸运的是,解决方案相当简单:只需将ProductDetail 设为一个单独的类,而不是从Product 派生。然后你会得到你正在寻找的表拆分:

    [Table("Product")]
    public class Product
    {
      [Key]
      public int ProductId { get; set; }
    
      public string Name { get; set; }
      public virtual ProductDetail Details { get; set; }
    }
    
    [Table("Product")]
    public class ProductDetail
    {
      [Key]
      public int ProductId { get; set; }
    
      public string Description { get; set; }
    }
    

    您还需要使用 Fluent API 在您的上下文中设置关系:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      base.OnModelCreating(modelBuilder);
    
      modelBuilder.Entity<Product>()
                  .HasRequired(p => p.Details)
                  .WithRequiredPrincipal();
    }
    

    然后您可以加载Product 并使用myProduct.Details.Description 访问描述(使用此设置,您可能不需要手动访问ctx.ProductDetails,如果有的话)。

    请注意,您必须启用延迟加载,或者使用 ctx.Products.Include(p =&gt; p.Details) 在您想要的所有查询中明确包含详细信息,才能使其正常工作。

    希望这会有所帮助!不同类型的表映射之间的区别有时可能非常微妙。

    【讨论】:

    • 谢谢!这个解释简明扼要,很有帮助,而且很有说服力。再问一个问题……您如何学习这些东西? 8-)
    • 只是想知道为什么有些东西没有用,并询问曾经走过这条路的人……这就是生活的循环!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多