摘要
我有三节课:Account
SpecialAccount
(继承自Account
)Profile
(与SpecialAccount
的0..1关系)
换句话说,SpecialAccount
可以具有0或1个Profiles
。 Profile
必须具有SpecialAccount
。
在EF中,只能将其设置为共享的主键关系。
当查询profile
并询问SpecialAccount
中的内容时(例如,在profile.SpecialAccount.Name == "blah"
中查找配置文件),我会收到此错误:
{“指定表达式的ResultType与所需类型不兼容。
表达式ResultType为'Transient.reference [EFInheritanceTest.Account]',但
必需的类型为“ Transient.reference [EFInheritanceTest.SpecialAccount]”。
\ r \ n参数名称:arguments 1“}
细节
此代码说明了该问题:
namespace EFInheritanceTest
{
class Program
{
static void Main(string[] args)
{
using (var context = new MyContext())
{
var t = context.Profiles.Where(p => p.SpecialAccount.Name == "Fred");
Console.WriteLine(t.Count());
Console.ReadKey();
}
}
}
public class MyContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
public DbSet<SpecialAccount> SpecialAccounts { get; set; }
public DbSet<Profile> Profiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<SpecialAccount>().HasOptional(a => a.Profile);
modelBuilder.Entity<Profile>().HasRequired(p => p.SpecialAccount);
}
}
public class Account
{
public int ID { get; set; }
public string Name { get; set; }
}
public class SpecialAccount : Account
{
public virtual Profile Profile { get; set; }
}
public class Profile
{
public int ID { get; set; }
public string Summary { get; set; }
public virtual SpecialAccount SpecialAccount { get; set; }
}
}
到目前为止的调查
基本上,罪魁祸首似乎是共享的主键关联。当
Profile
寻找其SpecialAccount
时,它将获取父Account
对象。我能看到的唯一解决方案是像这样更改它;
public class SpecialAccount : Account
{
public virtual ICollection<Profile> Profiles { get; set; }
}
并以代码形式维护规则,而不是使用数据库。但这很丑。
我在Connect上发现了与此相关的question和this bug-但已被标记为已解决!
我怀疑这是EF4.1中的错误,但如果有人对它有所了解或有所了解,那么我将不胜感激。
最佳答案
作为一种似乎无需更改模型定义即可工作的解决方法,可以使用联接:
var t = from p in context.Profiles
join s in context.SpecialAccounts
on p.ID equals s.ID
where s.Name == "Fred"
select p;
var count = t.Count();
或使用扩展方法:
var t = context.Profiles
.Join(context.SpecialAccounts,
p => p.ID,
s => s.ID,
(p, s) => new { s, p })
.Where(r => r.s.Name == "Fred");
var count = t.Count();
那不是很好,但是您的原始查询不起作用的事实确实对我来说就像是个错误。 (我已经用EF 4.1测试过)