1

对不起,但我对表格拆分感到困惑!

我有 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; }
}
4

1 回答 1

1

发生这种情况的原因是因为您ProductDetail继承自Product,从技术上讲,这使得这是一个按层次结构的表映射,而不是简单的表拆分。这意味着,无论何时加载 all Products,都必须同时加载 all ProductDetails。EF 知道如何区分这两者,因此在加载每个实体时,框架会将其分类到DbSet您的上下文中的适当位置——它们都被添加到Products集合中,但也有一些也被添加到ProductDetails集合中。

幸运的是,解决方案相当简单:只需创建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 => p.Details),才能使其正常工作。

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

于 2013-05-20T15:41:06.197 回答