对不起,但是我对表分裂感到困惑!
我有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; }
}
发生这种情况的原因是ProductDetail
继承了Product
,这在技术上使其成为按层次表的映射,而不是简单的表分割。这意味着,当你装载所有的Products
时,你也必须装载所有的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)
的所有查询中包含详细信息,以便使其工作。
希望这对你有帮助!不同类型的表映射之间的区别有时非常微妙。