使用Entity Framework时,我对在两个实体之间定义关系的位置感到困惑。我觉得无论何时我寻找例子,我最终都会从两个不同的角度找到相同的例子 - 依赖→委托,以及委托 - 依赖。
鉴于以下实体:
class Foo
{
public int Id { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
}
class Bar
{
public int Id { get; set; }
public Foo Foo { get; set; }
public virtual Baz { get; set; }
}
class Baz
{
public int Id { get; set; }
public Bar Bar { get; set; }
}
我们这里有几个场景。 Foo
有许多Bar
指向它。 Baz
具有Bar
的可选外键。 Baz
可以在未指定Bar
的情况下存在。
我在哪里定义这些关系?到底在哪里,我的意思是在使用流畅的API时,哪个实体会定义这些关系?也许更清楚一点,如果我使用流畅的API和EntityTypeConfiguration
类进行绑定,那么这些实体将被定义在哪个实体中?
为什么我感到困惑的一个例子是因为我看到像this one这样的答案,说明应该在班级中使用virtual
来定义一对一。因此,在这些实体中,Baz
和Bar
之间的可选一对一将是或类似于:
modelBuilder.Entity<bar>()
.HasOptional(f => f.Baz)
.WithRequired(s => s.Bar);
答案 0 :(得分:2)
我认为您对virtual
关键字感到困惑。我确实尝试在你链接的页面上找到它,但它不存在。
virtual
关键字允许实体框架覆盖它在幕后创建的代理实体中的该属性,并继承自Bar
。然后,当访问属性时,覆盖将对延迟加载Baz
进行数据库调用。
virtual
关键字与关系的定义无关,如果您不想延迟加载,则不需要它。
您在映射时定义主体:
modelBuilder.Entity<bar>()
.HasOptional(f => f.Baz). //Baz is dependent
.WithRequired(s => s.Bar);//Bar is principal
modelBuilder.Entity<bar>()
.HasOptional(f => f.Bar). //Bar is dependent
.WithRequired(s => s.Baz);//Baz is principal
至于您的示例中Foo
和Bar
之间的其他关系,Foo
的集合为Bars
但Foo
只有一个Bar
所以外键继续Bar
。 EF默认会这样做。
依赖项获取引用主体密钥的外键。如果它是一对一的,那个外键也是依赖的主键,但是EF无法解决哪个是哪个,这就是为什么在你指定错误之前就会出现错误的原因。
答案 1 :(得分:2)
当您使用在课程中定义的EF时,您已经定义了关系。 当您在类
中定义Collection中的导航属性时,EF能够理解 public virtual ICollection<Bar> Bars { get; set; }
你想要一对多的关系。
另一方面,如果您将一个集合添加到另一个类
public virtual ICollection<Foo> Foos { get; set; }
EF会明白你想要很多可能关系
如果你在另一个类中添加一个类实例作为属性,它会理解为一对一(或从零到一)关系。
虚拟关键字与您之前提到的关系无关,它涉及懒惰,急切加载