大家好,2017年新人快乐,
我有以下表格/对象结构。
[Table("Table1")]
public class Table1
{
[Key]
public long Table1Id { get; set; }
public virtual ICollection<Table2> ItemsOfTable2 { get; set; }
}
[Table("Table2")]
public class Table2
{
[Key]
public long Table2Id { get; set; }
public long Table1Id { get; set; }
[ForeignKey("Table1Id")]
public virtual Table1 Table1Object { get; set; }
public virtual ICollection<Table3Base> ItemsOfTable3 { get; set; }
[NotMapped]
public virtual ICollection<Table3Red> RedItems
{
get { return this.ItemsOfTable3.OfType<Table3Red>().ToList(); }
}
[NotMapped]
public virtual ICollection<Table3Blue> BlueItems
{
get { return this.ItemsOfTable3.OfType<Table3Blue>().ToList(); }
}
}
[Table("Table3Base")]
public abstract class Table3Base
{
[Key]
public long Table3Id { get; set; }
public long Table2Id { get; set; }
[ForeignKey("Table2Id")]
public virtual Table2 Table2Object { get; set; }
}
public class Table3Red : Table3Base
{
public string SpecialPropertyForRed { get; set; }
}
public class Table3Blue : Table3Base
{
public int SpecialPropertyForBlue { get; set; }
public virtual ICollection<Table4> ItemsOfTable4 { get; set; }
}
[Table("Table4")]
public class Table4
{
[Key]
public long Table4Id { get; set; }
public long Table3Id { get; set; }
[ForeignKey("Table3Id")]
public virtual Table3Blue Table3BlueObject { get; set; }
}
public class MyContext : DbContext
{
public virtual IDbSet<Table1> Table1DbSet { get; set; }
public virtual IDbSet<Table2> Table2DbSet { get; set; }
public virtual IDbSet<Table3Red> Table3RedDbSet { get; set; }
public virtual IDbSet<Table3Blue> Table3BlueDbSet { get; set; }
public virtual IDbSet<Table4> Table4DbSet { get; set; }
}
因此,在这个“树”的中间,有一个TPH结构(类Table3Base,Table3Red,Table3Blue存储在数据库表“Table3Base”中)。我们只有Table3Red和Table3Blue的IDbSets,而不是Table3Base。每个对象都有下一个表对象的集合导航属性。
Class Table3Blue具有Table4对象项的另一个集合导航属性。
进一步(但希望无关)信息:默认鉴别器映射到内部枚举:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
// TPH: Map Standard-Discriminator to Enum
modelBuilder.Entity<Table3Base>()
.Map<Table3Red>(m => m.Requires("Typ").HasValue((int)Table3TypEnum.Red))
.Map<Table3Blue>(m => m.Requires("Typ").HasValue((int)Table3TypEnum.Blue));
}
由于性能问题(逐个加载每个记录非常慢;延迟加载处于活动状态),我们希望通过包含这样的结构从表1到表4读取此结构:
var table1Records = this.m_Context.Table1DbSet
.Include(t => t.ItemsOfTable2)
.Include(t => t.ItemsOfTable2.Select(t2 => t2.ItemsOfTable3))
.Include(t => t.ItemsOfTable2.Select(t2 => t2.ItemsOfTable3.OfType<Table3Blue>().Select(t3 => t3.ItemsOfTable4)))
.ToList();
第一个和第二个包括似乎工作,但第三个包括抛出一个Argument异常“Include路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,Select运算符用于集合导航属性。 Parametername:path“。
我做错了什么?如何在前往数据库的途中包含Table4对象?
亲切的问候,伴侣
答案 0 :(得分:0)
这是我们的解决方法。我怀疑这是最好的解决方案,所以更好的方式受到高度赞赏......
Table3Base将集合导航属性作为虚拟属性获取到Table4。
Table3Red(没有Table4对象的对象)使用getter返回此属性来覆盖Table4对象的空列表,而不是setter。
因此,我们可以将Include级联到Table4而不进行任何类型检查。在我们的PTH数据库表中没有不必要的记录&#34; Table3Base&#34;。所以一切都很好,除了具有未使用的导航属性的Table3Red的笨拙定义。 : - (
BTW:包含长路径包括沿此路径的所有对象,因此显式&#34; .Include(A).Include(A.B).Include(A.B.C)&#34;没有必要; &#34; .INCLUDE(A.B.C)&#34;也会这样做。代码示例中的迭代.Include是为了清楚起见。
HTH,Mate