当前位置:编程学习 > C#/ASP.NET >>

跪求关于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指定依赖方向 --------------------编程问答--------------------
引用 1 楼 abbey 的回复:
从Recycler与RecyclerAcount的最后两行代码看,你准备建立1:1的关系,这需要用Annotion或者Fluent API指定依赖方向


能详细一点吗,我被这个问题困恼了很久,而且我发现我用dbContext.set<Quoter>.where(q=>q.ID ==1).ToList();返回的结果是ienumable<Recycler>类型的,我现在对entityframework的继承已经觉得是不是有设计上的Bug --------------------编程问答--------------------
引用 1 楼 abbey 的回复:
从Recycler与RecyclerAcount的最后两行代码看,你准备建立1:1的关系,这需要用Annotion或者Fluent API指定依赖方向

因为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 楼 tianma4872 的回复:
因为recycleraccount的关联是这样的recycleraccount的recycler字段即是recycleraccount的主键,同时是recycler表的外键,本来应该是1:M的关系,……


能简单说一下你业务建模里这3个对象之间的关系吗?不用说明谁是PK/FK,只说明三个对象间的关系即可。我越看越不明白你的需求了。 --------------------编程问答--------------------
引用 4 楼 abbey 的回复:
我将就我的练习,模拟了你的要求。象下面这样的建模,可以实现Recycler从Quoter派生,并与Account实现1:1的对应关系。
C# code
partial class BreakAwayContext
{
    public DbSet<Quoter> Quoters { get; set; }
    public DbSet<Account> Accounts { get;……


我是不是要重新根据模型生成一下数据库?,因为我现在的数据已经生成好了,也都映射好对应的关系了 --------------------编程问答--------------------
引用 5 楼 abbey 的回复:
引用 3 楼 tianma4872 的回复:
因为recycleraccount的关联是这样的recycleraccount的recycler字段即是recycleraccount的主键,同时是recycler表的外键,本来应该是1:M的关系,……


能简单说一下你业务建模里这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
--------------------编程问答--------------------
引用 7 楼 tianma4872 的回复:
Quoter是一个基类,它现在地下有一个派生类交Recycler,这两个类都有对应的数据表,通过TPT方式实现继承,每个Recycler都一个唯一的RecyclerAccount

Quoter与Recycler如何实现表的存储,无关紧要。关键是要建立Recycler与Account之间的1:1关系。这个可以通过象我上面那样的Fluent API实现,或者使用Data Annotation。

我之前的代码已经可以实现你的要求。 --------------------编程问答-------------------- 这是上述代码生成的模型
--------------------编程问答--------------------
引用 10 楼 abbey 的回复:
这是上述代码生成的模型


我照你的方法去试了,发现没用啊
--------------------编程问答--------------------
引用 11 楼 tianma4872 的回复:
引用 10 楼 abbey 的回复:

这是上述代码生成的模型


我照你的方法去试了,发现没用啊


能把你的源代码发给我看一下吗,我的邮箱:tgmj_001@sohu.com --------------------编程问答-------------------- 刚才贴的已经就是全部代码了啊。
public class BreakAwayContext : 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代码试一下

        }
}
--------------------编程问答-------------------- 新建一个控制台应用,把上面的代码贴进去。如果你用的SQL Server Express,那么EF会自动建立数据库连接并生成对应的表。如果不是Express,需要你自己配置数据库连接串,比如在app.config里,或者传送给DbContext的构造子。 --------------------编程问答--------------------
引用 13 楼 abbey 的回复:
刚才贴的已经就是全部代码了啊。
C# code
public class BreakAwayContext : DbContext
{
    public DbSet<Quoter> Quoters { get; set; }
    public DbSet<Account> Accounts { get; set; }

    protected override void OnMo……


那就奇怪了, 我也照你这样的方式去试了,没有用啊,异常一样存在啊, --------------------编程问答-------------------- 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();
--------------------编程问答--------------------
引用 16 楼 abbey 的回复:
Sorry,刚才只留意你要建立Recycle与Account之间1:1的关系去了。触发异常,是因为Include<T,  TProperty>()这里的问题。由于Quoter是抽象类,且Recycler是用的Quoter的PK与Account建立的关系,因此我暂时想到的办法,是换作如下的思路。

即适当修改一下Fluent,建立Quoter与Account之间1:1的关系。
C# code……

对的,这样处理是可以的,但这样做account就变成了quoter的导航属性了,我其实是想让account成为recycler的导航属性,这样从面向domain上来讲更有意义,因为这个account是为recycler建立的,并不是所有的quoter都有account --------------------编程问答-------------------- 找到问题了,不在Include<T, TProperty>(),而在你最后的ToList()。

你把ToList()去除,这个查询就能正常执行了,不过我还没Seed数据进去,不知道这个查询是否能返回我们需要的结果。先睡觉了,明天我再看看。 --------------------编程问答--------------------
引用 18 楼 abbey 的回复:
找到问题了,不在Include<T, TProperty>(),而在你最后的ToList()。

你把ToList()去除,这个查询就能正常执行了,不过我还没Seed数据进去,不知道这个查询是否能返回我们需要的结果。先睡觉了,明天我再看看。


ToList去掉了,数据怎么出来? 辛苦你了老兄 --------------------编程问答-------------------- 想了一中午,也没找到合适的办法解决这个问题。昨晚睡觉前,我把你的问题提交到StackOverflow了,有空就去看看人家的回复吧。

Why can't I do ToList()?
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,