跪求关于entityframework TPT继承 预加载子类的导航属性
POCO类定义如下:
public partial class Quoter
{
public int ID { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public string Contactor { get; set; }
public System.DateTime RegisterDt { get; set; }
public int Status { get; set; }
public bool Active { get; set; }
}
public partial class Recycler : Quoter
{
public Recycler()
{
this.ContactInfo = new RecylerContactInfo();
this.CertificatedInfo = new RecylerCertificatedInfo();
this.ShopInfo = new RecylerShopInfo();
this.ClientAppStat = new RecylerClientAppStat();
}
public string Description { get; set; }
public int Region { get; set; }
public bool IsReal { get; set; }
public int Group { get; set; }
public string Remark { get; set; }
public Nullable<int> Order { get; set; }
public RecylerContactInfo ContactInfo { get; set; }
public RecylerCertificatedInfo CertificatedInfo { get; set; }
public RecylerShopInfo ShopInfo { get; set; }
public RecylerClientAppStat ClientAppStat { get; set; }
public virtual Region RegionInfo { get; set; }
public virtual RecylerGroup RecylerGroup { get; set; }
public virtual RecylerStat RecylerStat { get; set; }
public virtual RecyclerAccount RecyclerAccount { get; set; }
}
public partial class RecyclerAccount
{
public int Recycler { get; set; }
public int Credit { get; set; }
public int Sum { get; set; }
public int Available { get; set; }
public string Guarantee { get; set; }
public virtual Recycler RecyclerInfo { get; set; }
}
现在我要查找recycler并且预加载它的导航属性RecyclerAccount,我用下面两只方式尝试均不成功
dbContext.set<Recycler>().include(r=>r.RecyclerAccount).where(r.ID == 1).ToList();
这里抛出的异常信息是:{"指定表达式的 ResultType 与要求的类型不兼容。表达式 ResultType 为“Transient.reference[HuiShou.Quoter]”,但要求的类型为“Transient.reference[HuiShou.Recycler]”。\r\n参数名: arguments[0]"}
我又换成下面的方式查找
dbContext.set<Quoter>().oftype<Recycler>().include(r=>r.RecyclerAccount).where(r=>r.ID == 1).ToList();
这次代码可以顺利执行,但是执行结果发现recycler的导航属性RecyclerAccount没有预加载进来还是为null,看了entityframework生成的sql代码确实没有关联recycleraccount表,只关联了quoter和recycler表
这是怎么回事,正确的处理方法是怎么样的啊 --------------------编程问答-------------------- 从Recycler与RecyclerAcount的最后两行代码看,你准备建立1:1的关系,这需要用Annotion或者Fluent API指定依赖方向 --------------------编程问答--------------------
能详细一点吗,我被这个问题困恼了很久,而且我发现我用dbContext.set<Quoter>.where(q=>q.ID ==1).ToList();返回的结果是ienumable<Recycler>类型的,我现在对entityframework的继承已经觉得是不是有设计上的Bug --------------------编程问答--------------------
因为recycleraccount的关联是这样的recycleraccount的recycler字段即是recycleraccount的主键,同时是recycler表的外键,本来应该是1:M的关系,但因为recycler字段是recycleraccount的主键所以变成了1:1的关系 --------------------编程问答-------------------- 我将就我的练习,模拟了你的要求。象下面这样的建模,可以实现Recycler从Quoter派生,并与Account实现1:1的对应关系。
partial class BreakAwayContext--------------------编程问答--------------------
{
public DbSet<Quoter> Quoters { get; set; }
public DbSet<Account> Accounts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>().HasRequired(a => a.RecyclerRef).WithRequiredDependent(r => r.AccountRef);
}
}
public abstract class Quoter
{
public int QuoterId { get; set; }
public string Text { get; set; }
}
public class Recycler : Quoter
{
public string Description { get; set; }
public Account AccountRef { get; set; }
}
public class Account
{
public int AccountId { get; set; }
public Recycler RecyclerRef { get; set; }
}
能简单说一下你业务建模里这3个对象之间的关系吗?不用说明谁是PK/FK,只说明三个对象间的关系即可。我越看越不明白你的需求了。 --------------------编程问答--------------------
我是不是要重新根据模型生成一下数据库?,因为我现在的数据已经生成好了,也都映射好对应的关系了 --------------------编程问答--------------------
好的,
Quoter是一个基类,它现在地下有一个派生类交Recycler,这两个类都有对应的数据表,通过TPT方式实现继承,
每个Recycler都一个唯一的RecyclerAccount --------------------编程问答-------------------- 没有数据吧?没有就重建吧。有的话,就要想点办法了。
那天你发的帖子,我也能建立B从A派生,B与C形成1:M的关系的模型。
Relationship是EF里的难点了,给你推荐一个人的blog吧。这是该系列的第一篇:
http://weblogs.asp.net/manavi/archive/2011/03/27/associations-in-ef-4-1-code-first-part-1-introduction-and-basic-concepts.aspx
--------------------编程问答--------------------
Quoter与Recycler如何实现表的存储,无关紧要。关键是要建立Recycler与Account之间的1:1关系。这个可以通过象我上面那样的Fluent API实现,或者使用Data Annotation。
我之前的代码已经可以实现你的要求。 --------------------编程问答-------------------- 这是上述代码生成的模型
--------------------编程问答--------------------
我照你的方法去试了,发现没用啊
--------------------编程问答--------------------
能把你的源代码发给我看一下吗,我的邮箱:tgmj_001@sohu.com --------------------编程问答-------------------- 刚才贴的已经就是全部代码了啊。
public class BreakAwayContext : DbContext--------------------编程问答-------------------- 新建一个控制台应用,把上面的代码贴进去。如果你用的SQL Server Express,那么EF会自动建立数据库连接并生成对应的表。如果不是Express,需要你自己配置数据库连接串,比如在app.config里,或者传送给DbContext的构造子。 --------------------编程问答--------------------
{
public DbSet<Quoter> Quoters { get; set; }
public DbSet<Account> Accounts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>()
.HasRequired(a => a.RecyclerRef)
.WithRequiredDependent(r => r.AccountRef);
}
}
public abstract class Quoter
{
public int QuoterId { get; set; }
public string Text { get; set; }
}
public class Recycler : Quoter
{
public string Description { get; set; }
public Account AccountRef { get; set; }
}
public class Account
{
public int AccountId { get; set; }
public Recycler RecyclerRef { get; set; }
}
public class PocoExercise
{
static void Main(string[] args)
{
// 这里自己添加一点CUD代码试一下
}
}
那就奇怪了, 我也照你这样的方式去试了,没有用啊,异常一样存在啊, --------------------编程问答-------------------- Sorry,刚才只留意你要建立Recycle与Account之间1:1的关系去了。触发异常,是因为Include<T, TProperty>()这里的问题。由于Quoter是抽象类,且Recycler是用的Quoter的PK与Account建立的关系,因此我暂时想到的办法,是换作如下的思路。
即适当修改一下Fluent,建立Quoter与Account之间1:1的关系。
modelBuilder.Entity<Account>()
.HasRequired(a => a.QuoterRef)
.WithRequiredDependent(r => r.AccountRef);
然后用类似下面这样的查询:
var query = context.Quoters--------------------编程问答--------------------
.Include(q => q.AccountRef)
.OfType<Recycler>()
.Where(r=>r.QuoterId == 1)
.ToList();
对的,这样处理是可以的,但这样做account就变成了quoter的导航属性了,我其实是想让account成为recycler的导航属性,这样从面向domain上来讲更有意义,因为这个account是为recycler建立的,并不是所有的quoter都有account --------------------编程问答-------------------- 找到问题了,不在Include<T, TProperty>(),而在你最后的ToList()。
你把ToList()去除,这个查询就能正常执行了,不过我还没Seed数据进去,不知道这个查询是否能返回我们需要的结果。先睡觉了,明天我再看看。 --------------------编程问答--------------------
ToList去掉了,数据怎么出来? 辛苦你了老兄 --------------------编程问答-------------------- 想了一中午,也没找到合适的办法解决这个问题。昨晚睡觉前,我把你的问题提交到StackOverflow了,有空就去看看人家的回复吧。
Why can't I do ToList()?
补充:.NET技术 , C#