Entity framework 与实体框架的1对1可选关系
我正在绞尽脑汁想知道为什么实体框架在以下上下文中不允许1对1关系Entity framework 与实体框架的1对1可选关系,entity-framework,entity-framework-6,Entity Framework,Entity Framework 6,我正在绞尽脑汁想知道为什么实体框架在以下上下文中不允许1对1关系 ClassA { public int ID; [ForeignKey("ClassB")] public int ClassBID; public ClassB classB; } ClassB { public int ID; [ForeignKey("ClassA")] public int ClassAID; public ClassA classa; } i、 e.一对
ClassA {
public int ID;
[ForeignKey("ClassB")]
public int ClassBID;
public ClassB classB;
}
ClassB {
public int ID;
[ForeignKey("ClassA")]
public int ClassAID;
public ClassA classa;
}
i、 e.一对一的关系,我可以从linq导航到任何一个
我的背景是我有一辆车。每辆车都可以有一个装置(如果没有,则为空)。每个设备将有一个可选的车辆
如果有人能解释为什么他上面的说法是无效的(或不受支持的),并解释我将如何回避我的问题,我会非常感激
提前感谢。如果我知道一台设备可以有零辆或一辆车,反之亦然。
在旧的DB模型中,两个表(设备或车辆)中的一个应具有引用另一个表的可空字段。
要在EF中配置它,您必须使用数据注释或fluent接口。 这里是模型和上下文的代码
public class ClassA
{
public int Id { get; set; }
public string Description { get; set; }
public virtual ClassB ClassB { get; set; }
}
public class ClassB
{
public int Id { get; set; }
public string Description { get; set; }
public virtual ClassA ClassA { get; set; }
}
class Context : DbContext
{
public Context(DbConnection connection)
: base(connection, false)
{ }
public DbSet<ClassA> As { get; set; }
public DbSet<ClassB> Bs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ClassB>().HasOptional(c => c.ClassA).WithOptionalDependent(c => c.ClassB);
}
}
现在是最后一步。。。
从数据库的结构来看,这个POCO模型是
ClassBs(Id, Description, ClassA_Id : ClassAs)
ClassAs(Id, Description)
在DB模型中,我们可以有两个不同的ClassB实例,它们具有相同的ClassA实例(EF不允许我们这样做,但我们可以通过SQL这样做)。
在使用SQL进行黑客攻击之后,您可以运行此测试
using (Context context = new Context(connection))
{
foreach (var classB in context.Bs.ToList())
{
if (classB.ClassA == null)
continue;
Console.WriteLine("{0} {1} {2}", classB.Id, classB.ClassA.Id, classB.ClassA.ClassB.Id);
}
}
此测试引发异常
==EntityFramework.dll中发生类型为“System.InvalidOperationException”的未处理异常 其他信息:发生关系多重性约束冲突:EntityReference不能有多个相关对象,但查询返回多个相关对象。这是一个不可恢复的错误 ===
我们可以避免SQL中的某个人这样做吗?是的,在ClassA_Id字段中插入唯一约束。您必须确定一端是非可选的(即,允许1到0..1,不允许0..1到0..1)。一旦您这样做,EF通过强制依赖方不拥有自己的
Key
,而是将依赖类“Key
”定义为与其ForeignKey
相同,从而支持1对0..1(如果您仔细想想,这对于假定为1对1的关系是有意义的):
请注意,SQL中的
BId
是int?
:NULL
与C#中的NULL
相对应。非常感谢您的验证。因此,在这种情况下,如果不使用fluentapi,就无法解决问题?(我问这个问题的唯一原因是因为我更喜欢尝试将类中的所有内容都作为属性保存,因为我个人认为这很容易阅读和理解:))事实上,我认为这是不可能的。
using (Context context = new Context(connection))
{
foreach (var classB in context.Bs.ToList())
{
if (classB.ClassA == null)
continue;
Console.WriteLine("{0} {1} {2}", classB.Id, classB.ClassA.Id, classB.ClassA.ClassB.Id);
}
}
class A
{
public int Id { get; set; }
public int? BId { get; set; }
public virtual B B { get; set; }
}
class B
{
[Key, ForeignKey("A")]
public int Id { get; set; }
public virtual A A { get; set; }
}