Entity Framework - 包括派生自基本 DBSet 的集合
Entity Framework - Including Collections on Derived from Base DBSet
我要问的主要问题是:
Is there a way to keep a DbSet based off the base class and still support eager loading for a Derived object in a single retrieve method that only requires an Id? The answer may be that you can't. I'm just hoping I'm overlooking something.
考虑以下情况:
//Models
public class Base {
public int Id {get;set;}
public string BaseProp {get;set;}
}
public class Derived : Base {
public string DerivedProp {get;set;}
}
//Context
DbSet<Base> Bases {get;set;}
//Saving
public void Save(Base obj){
// Adding only for brevity
context.Bases.Add(obj)
context.SaveChanges();
}
//Retrieval
public Base Retrieve(int id){
return context.Bases.FirstOrDefault(x => x.Id == id);
}
EF6 足够聪明,可以知道 Base 对象何时实际上是 Derived 对象,并在保存时填充附加字段以及将对象检索为 Derived 对象。
但是,如果我将派生的 class 更改为:
public class Derived : Base {
public string DerivedProp {get;set;}
public ICollection<SomeLookup> Lookup {get; set;} // Creates junction table with Id/LookupId as columns
}
我仍然可以保存(并且它用选定的查找完美地填充了连接点 table),但是我无法再检索我的 Base DbSet 中的完整对象,因为我无法将其更改为具有渴望包含在 Base 不知道存在的集合中。
我可以虚拟化集合,这样当映射发生时它会延迟加载,但我想知道,这是根本问题:
更新: 基本上我想知道的是,如果我只有一个 Id 可用于我的检索,则以下内容将不起作用,但是是否有类似的东西会吗?
context.Bases.Include(x => ((Derived)x).Lookup).FirstOrDefault(x => x.Id == id)
用例是我有一个列表页面。该页面不需要关心它是什么类型,因为它只有基本属性。如果我进入其中一个编辑页面,服务器只会传递 ID。
如果这是唯一的方法,我将接受延迟加载,因为在检索后构建 DTO 时会发生这种情况,但我想知道是否有一些我不知道的 modelBuilder EF 配置或者一种编写项目查询的方法,我还没有找到它允许对派生查找集合进行预加载?
更新 2: 基于他让我知道我不能做我希望的事情而接受的答案。还发现 this on the EF uservoice.
Essentially all I want to know is, if I only have an Id to work with for my retrieve, the following wont work, but is there something like it that will?
如果您的派生对象使用某种类型的 Entity Framework 继承; Mapping the Table-Per-Type (TPT) Inheritance or Mapping the Table-Per-Hierarchy (TPH) Inheritance or Mapping the Table-Per-Concrete Class (TPC) Inheritance。
然后是,
db.Bases
.OfType<Derived>()
.Include(d => d.Lookup)
.Where(d => d.Id = someId)
.ToList();
否则不会,不会
我要问的主要问题是:
Is there a way to keep a DbSet based off the base class and still support eager loading for a Derived object in a single retrieve method that only requires an Id? The answer may be that you can't. I'm just hoping I'm overlooking something.
考虑以下情况:
//Models
public class Base {
public int Id {get;set;}
public string BaseProp {get;set;}
}
public class Derived : Base {
public string DerivedProp {get;set;}
}
//Context
DbSet<Base> Bases {get;set;}
//Saving
public void Save(Base obj){
// Adding only for brevity
context.Bases.Add(obj)
context.SaveChanges();
}
//Retrieval
public Base Retrieve(int id){
return context.Bases.FirstOrDefault(x => x.Id == id);
}
EF6 足够聪明,可以知道 Base 对象何时实际上是 Derived 对象,并在保存时填充附加字段以及将对象检索为 Derived 对象。
但是,如果我将派生的 class 更改为:
public class Derived : Base {
public string DerivedProp {get;set;}
public ICollection<SomeLookup> Lookup {get; set;} // Creates junction table with Id/LookupId as columns
}
我仍然可以保存(并且它用选定的查找完美地填充了连接点 table),但是我无法再检索我的 Base DbSet 中的完整对象,因为我无法将其更改为具有渴望包含在 Base 不知道存在的集合中。
我可以虚拟化集合,这样当映射发生时它会延迟加载,但我想知道,这是根本问题:
更新: 基本上我想知道的是,如果我只有一个 Id 可用于我的检索,则以下内容将不起作用,但是是否有类似的东西会吗?
context.Bases.Include(x => ((Derived)x).Lookup).FirstOrDefault(x => x.Id == id)
用例是我有一个列表页面。该页面不需要关心它是什么类型,因为它只有基本属性。如果我进入其中一个编辑页面,服务器只会传递 ID。
如果这是唯一的方法,我将接受延迟加载,因为在检索后构建 DTO 时会发生这种情况,但我想知道是否有一些我不知道的 modelBuilder EF 配置或者一种编写项目查询的方法,我还没有找到它允许对派生查找集合进行预加载?
更新 2: 基于他让我知道我不能做我希望的事情而接受的答案。还发现 this on the EF uservoice.
Essentially all I want to know is, if I only have an Id to work with for my retrieve, the following wont work, but is there something like it that will?
如果您的派生对象使用某种类型的 Entity Framework 继承; Mapping the Table-Per-Type (TPT) Inheritance or Mapping the Table-Per-Hierarchy (TPH) Inheritance or Mapping the Table-Per-Concrete Class (TPC) Inheritance。
然后是,
db.Bases
.OfType<Derived>()
.Include(d => d.Lookup)
.Where(d => d.Id = someId)
.ToList();
否则不会,不会