Entity framework 如何获得组合可选关系和一对多关系?
我对如何在实体框架中建模我的关系感到困惑 我希望Entity framework 如何获得组合可选关系和一对多关系?,entity-framework,foreign-keys,relationships,data-modeling,Entity Framework,Foreign Keys,Relationships,Data Modeling,我对如何在实体框架中建模我的关系感到困惑 我希望ClassA可以选择性地指向aClassB。 这听起来像是一种可选的一对一关系 我还希望ClassB始终指向指向它的ClassA。 我还想允许多个ClassB引用同一ClassA。这听起来像是一对多的关系 这是一种关系,还是两种完全不同的关系 如果是两个关系,它们能否共享ClassB上显示的用于引用ClassA的单个属性“ClassAKey” 在我的问题中,我的头脑中清楚地知道我希望我的OM是什么: ClassA { [Key] i
ClassA
可以选择性地指向aClassB
。
这听起来像是一种可选的一对一关系
我还希望ClassB
始终指向指向它的ClassA。
我还想允许多个ClassB
引用同一ClassA
。这听起来像是一对多的关系
这是一种关系,还是两种完全不同的关系
如果是两个关系,它们能否共享ClassB上显示的用于引用ClassA的单个属性“ClassAKey”
在我的问题中,我的头脑中清楚地知道我希望我的OM是什么:
ClassA
{
[Key]
int Key { get; set; }
ClassB Maybe { get; set; }
int MaybeKey { get; set; }
}
ClassB
{
[Key]
int Key { get; set; }
ClassA Always { get; set; }
int AlwaysKey { get; set; }
}
我的头脑中也很清楚DB中应该是什么样子:对于ClassB
应该只有一个ClassAKey
列,对于ClassA
应该只有一个ClassBKey
列,这样每个列都可以相互引用,并且在这些列上有外键关系
但是。。。我不清楚如何在EF中对此进行建模。
事实上,看起来我一定是做错了什么!
如果我只是从上面的代码开始,我会得到一个错误
无法确定类型“ClassA”和“ClassB”之间关联的主端。必须使用关系fluent API或数据批注显式配置此关联的主端。
如果我尝试这样配置它
modelBuilder.Entity<ClassA>()
.HasOptional(a => a.Maybe)
.WithRequired(b => b.Always);
应该是t.AlwaysKey,对吧?
发生什么事了 如果我理解正确,您正试图在
ClassA
和ClassB
之间创建一个:多个可选关系。听起来你总是希望ClassB
有一个相关的ClassA
,这将使ClassA
成为你的委托人,而ClassB
成为你的依亲亲属
首先,您必须更改ClassB
的导航属性(在ClassA
中)。由于您需要多个关系,因此需要某种集合来存储ClassB
对象
这意味着您将删除ClassA
中的MaybeKey
,因为您所引用的对象不是一个,而是一个集合(例如ICollection
)。您也不需要相应的ClassA
表中的一列来引用ClassB
(因为它是一个一对多关系,单个列不起作用)。在ClassB
表中应该只需要有一个外键列,它指的是与ClassB
相关的ClassA
您的代码可能如下所示:
public class ClassA
{
[Key]
public int Key { get; set; } // ClassA Key
public virtual ICollection<ClassB> MyClassBs { get; set; } // Your optional dependants.
}
public class ClassB
{
[Key]
public int Key { get; set; } // ClassB key
public int AKey { get; set; } // Your foreign key.
public virtual ClassA myClassA { get; set; } // Your principal.
}
有几种不同的表达方式(例如,您可以从ClassB
侧进行)
对于主键,可能需要使用稍微传统一点的命名,例如ID
,而对于外键,则需要使用ClassAID
等名称,因为Entity framework有许多可供使用的名称。它还使其他人更容易阅读您的代码(因为您往往会遇到类似的约定)
编辑:更新以包括“特殊”关系
在ClassA
中,您可以包含以下字段(您在原始示例中已经使用了不同的名称):
并添加以下映射:
modelBuilder.Entity<ClassA>()
.HasOptional(x => x.SpecialB)
.WithMany()
.HasForeignKey(x => x.SpecialBID);
最后,我认为这是应该起作用的,但我没有让它起作用(这可能是Entity Framework 5中的一个bug):
第二个可选关系是按约定工作的,而不是显式配置。我不确定是否能得到它,但如果您尝试从现有数据库生成.edmx,会得到什么?嗯,有趣的答案。我的意见是,我实际上不应该需要MyClassB的集合。我不确定如果我懒散地加载了该集合并且从不使用它,那么它是否会带来很大的伤害。你的答案也遗漏了一件对我来说很重要的事情,那就是ClassA没有选择地拥有一个关联的ClassB,它是其集合中的“特殊”成员。这肯定对我有帮助!它变得有点复杂,但里面可能有一些有用的东西
modelBuilder.Entity<ClassA>()
.HasMany(b => b.MyClassBs) // Many ClassBs
.WithRequired(a => a.myClassA) // Each ClassB requires a ClassA
.HasForeignKey(b => b.AKey); // Use Akey as a foreign key
public int SpecialBID { get; set; }
public virtual ClassB SpecialB { get; set; }
modelBuilder.Entity<ClassA>()
.HasOptional(x => x.SpecialB)
.WithMany()
.HasForeignKey(x => x.SpecialBID);
modelBuilder.Entity<ClassB>()
.HasRequired(x => x.myClassA)
.WithMany()
.HasForeignKey(x => x.AKey);
modelBuilder.Entity<ClassB>()
.HasRequired(a => a.Always)
.WithMany()
.HasForeignKey(a => a.AlwaysKey);
modelBuilder.Entity<ClassB>()
.HasOptional(b => b.Maybe);
modelBuilder.Entity<ClassB>()
.HasRequired(a => a.Always)
.WithMany()
.HasForeignKey(a => a.AlwaysKey);
//modelBuilder.Entity<ClassB>()
// .HasOptional(b => b.Maybe);
int? MaybeKey { get; set; }