我知道关于这个主题有很多问题,但我还没有找到一个真正解释如何解决我的特定问题的问题。我认为这意味着它可能无法解决(我认为这可能与 EF 的思维方式“倒退”),但我不得不问。
我有一个带有三个(缩写)POCO 的模型,如下所示:
[Table("People")]
public class Person {
public int PersonID { get; set; }
[Required]
public string PersonName { get; set; }
}
public class Location {
public int LocationID { get; set; }
public int LocationTypeID { get; set; }
public virtual LocationType LocationType { get; set; }
}
public class Van : Location {
public int PartyID { get; set; }
public virtual Party Party { get; set; }
}
这些由(缩写的)数据库表支持(我们手工编写):
CREATE TABLE People (
PersonID INTEGER IDENTITY NOT NULL,
PersonName VARCHAR(255) NOT NULL,
PRIMARY KEY (PersonID)
)
CREATE TABLE Locations (
LocationID INTEGER IDENTITY NOT NULL,
LocationTypeID INTEGER NOT NULL,
FOREIGN KEY (LocationTypeID) REFERENCES LocationTypes(LocationTypeID)
)
CREATE TABLE Vans (
LocationID INTEGER NOT NULL,
PersonID INTEGER NOT NULL,
PRIMARY KEY (LocationID),
FOREIGN KEY (LocationID) REFERENCES Locations(LocationID),
FOREIGN KEY (PersonID) REFERENCES People(PersonID)
)
你大概可以想象它的LocationTypes
样子。
Locations
是每个类型的表层次结构的根 - 也有检查约束来强制执行这一点。Vans
是一种位置,就像其他不相关的东西一样Warehouse
。
现在,aVan
属于 a Person
,因为我们向员工发放一辆面包车,他们有责任给它加满燃料,而不是把它撞坏,把它带到客户现场并在他们用完所有供应的东西时订购更多的东西螺钉、钻头和铠装直流电缆。然而,并不是每个Person
人都有一辆面包车(其中一些在一辆面包车中成对工作),并且该Person
表没有指向的外键Van
- 它是相反的。这在某种意义上是一个历史事故,但它非常巧妙地模拟了这种情况,因为虽然 aPerson
不必有 a Van
,但 aVan
肯定必须有一个人。
所以我的问题是:我如何才能Person
拥有一个包含它们的导航属性Van
?
public virtual Van Van { get; set; }
我在数据注释和流畅的 API 方面做了很多工作,我得到的最接近的是OnModelCreating
:
modelBuilder.Entity<Van>()
.HasRequired(v => v.Person)
.WithOptional(p => p.Van);
不幸的是,这试图Van
用产生Location
对象的代理填充属性。它甚至可能是正确的Location
对象(我无法检查),但没有意识到它应该在寻找货车。但是,我确实怀疑它可能会在查找时尝试匹配PersonID
-LocationID
如果没有 Fluent API 映射,我根本就没有货车,这是我所期望的(所有PersonID
值都低于最低LocationID
值这对应于货车,所以不可能找到任何东西)。
Person
如果对 有一个可以为空的外键,这无疑会很容易Van
,但是我们在两个方向上都有外键,如果我们从中取出一个,Van
那么我们就不会对 aVan
具有 a的绝对必要约束进行建模Person
.
所以,我想,Van
拥有这种关系,并且Van
属性 onPerson
是一个反向导航属性,但似乎 EF 并不擅长这种一对一的技巧,即使一端是可选的。有没有办法让它发挥作用,还是我必须接受妥协?
我们通常拒绝因为 Entity Framework 缺少的特性而破坏数据库模型。我真正需要的是一种方法告诉 EF可以通过加入 Vans 上的 Vans.PersonID = Person.PersonID 来填充 on 上的Van
属性。Person