Entity Framework - 流畅 API 映射
Entity Framework - Fluent API Mapping
public class Customer
{
public int Id { get; set; }
public int AddressId { get; set; }
public virtual Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public virtual Customer { get; set; }
}
客户必须有地址。地址可能有也可能没有客户。地址中的客户导航 属性 类似于 "nullable"。我在 Customer.AddressId table 中有一个唯一索引。
有什么方法可以使用 fluent API 来做这个映射吗?
编辑:
CREATE TABLE Address
(
Id INT NOT NULL IDENTITY PRIMARY KEY,
AddressLine1 VARCHAR(50),
)
CREATE TABLE Customer
(
Id INT NOT NULL IDENTITY PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
AddressId INT NOT NULL,
CONSTRAINT FK_Customer_Address FOREIGN KEY(AddressId) REFERENCES Address (Id)
)
我重新创建了整个数据库和模型,并且能够向客户和地址添加记录 table。
基本上,如果一个客户只能有一个地址,那么这意味着一个地址可以有 0 个或多个客户。 (不是 0 或 1)理想情况下。
但由于您的唯一性限制,地址总是以 0 或 1 条客户记录结尾。但这是一个运行时约束,EF 在设计时并不知道这一点。 (我认为它不能完全掌握 2 种关系的唯一性规则)EF 将 Address-to-Customer 建模为 0:N,并让运行时处理 N 永远不会超过 1 的事实。
这是因为想起了记录
- 一个customerA记录,需要有一个AddressA记录
- AddressB 记录可以独立插入地址 table。
- Customertable中的另一条CustomerC记录需要肯定有Address记录,而这条记录需要是AddressB或AddressC。 (由于唯一索引约束,不能是AddressA)
- AddressD 记录可以独立插入地址 table。
所以AddressA有1条客户记录,AddressD有0条客户记录。
现在的问题是,您的 SQL 服务器知道一条客户记录只能有一个地址记录,并且该地址记录必须是唯一的。
EF 无法理解双向意义上的唯一性部分。它知道客户只需要一个地址,但不能强制要求该地址必须是唯一的。如果您尝试插入一个地址已经属于另一个客户的客户,当底层 INSERT 抛出错误时,自然会发生此错误。由于唯一性约束,EF 实际上在创建模型方面做得很好,在 Customer 和 Address 之间有 1:1。
但是因为它不能双向理解唯一性部分,所以它将多个客户映射到一个地址。 (0 或更多客户,而不是 0 或 1)
因此您的映射需要如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>()
.HasMany(e => e.Customers)
.WithRequired(e => e.Address)
.WillCascadeOnDelete(false);
}
这确保客户始终具有所需的地址实体,并且地址具有 0 个或多个客户。 (在实践中,由于唯一性约束,您将始终只在该列表中得到 0 或 1 个客户)但您不能在 EF 中强制执行它。您需要始终获取 List<Customers>
并且它始终具有 0 或 1 个元素。
如果您尝试手动修改映射并在 Address 和 Customer 之间有一个可选的 0:1 关系(而不是 0:N),那么 EF 会有点困惑并开始抛出 IDENTITY 插入异常一些理由。不知道为什么。
因此您可以使用上述映射,并确保在 List<Customers>
中始终只有 0 条或 1 条记录
已经有功能请求来完全理解双方的独特性方面(我认为转化为一个很好理解的关系代数)。 https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1050579-unique-constraint-i-e-candidate-key-support
public class Customer
{
public int Id { get; set; }
public Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public int? CustomerId { get; set; }
public virtual Customer { get; set; }
}
public class Customer
{
public int Id { get; set; }
public int AddressId { get; set; }
public virtual Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public virtual Customer { get; set; }
}
客户必须有地址。地址可能有也可能没有客户。地址中的客户导航 属性 类似于 "nullable"。我在 Customer.AddressId table 中有一个唯一索引。
有什么方法可以使用 fluent API 来做这个映射吗?
编辑:
CREATE TABLE Address
(
Id INT NOT NULL IDENTITY PRIMARY KEY,
AddressLine1 VARCHAR(50),
)
CREATE TABLE Customer
(
Id INT NOT NULL IDENTITY PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
AddressId INT NOT NULL,
CONSTRAINT FK_Customer_Address FOREIGN KEY(AddressId) REFERENCES Address (Id)
)
我重新创建了整个数据库和模型,并且能够向客户和地址添加记录 table。
基本上,如果一个客户只能有一个地址,那么这意味着一个地址可以有 0 个或多个客户。 (不是 0 或 1)理想情况下。 但由于您的唯一性限制,地址总是以 0 或 1 条客户记录结尾。但这是一个运行时约束,EF 在设计时并不知道这一点。 (我认为它不能完全掌握 2 种关系的唯一性规则)EF 将 Address-to-Customer 建模为 0:N,并让运行时处理 N 永远不会超过 1 的事实。
这是因为想起了记录
- 一个customerA记录,需要有一个AddressA记录
- AddressB 记录可以独立插入地址 table。
- Customertable中的另一条CustomerC记录需要肯定有Address记录,而这条记录需要是AddressB或AddressC。 (由于唯一索引约束,不能是AddressA)
- AddressD 记录可以独立插入地址 table。
所以AddressA有1条客户记录,AddressD有0条客户记录。
现在的问题是,您的 SQL 服务器知道一条客户记录只能有一个地址记录,并且该地址记录必须是唯一的。
EF 无法理解双向意义上的唯一性部分。它知道客户只需要一个地址,但不能强制要求该地址必须是唯一的。如果您尝试插入一个地址已经属于另一个客户的客户,当底层 INSERT 抛出错误时,自然会发生此错误。由于唯一性约束,EF 实际上在创建模型方面做得很好,在 Customer 和 Address 之间有 1:1。
但是因为它不能双向理解唯一性部分,所以它将多个客户映射到一个地址。 (0 或更多客户,而不是 0 或 1)
因此您的映射需要如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>()
.HasMany(e => e.Customers)
.WithRequired(e => e.Address)
.WillCascadeOnDelete(false);
}
这确保客户始终具有所需的地址实体,并且地址具有 0 个或多个客户。 (在实践中,由于唯一性约束,您将始终只在该列表中得到 0 或 1 个客户)但您不能在 EF 中强制执行它。您需要始终获取 List<Customers>
并且它始终具有 0 或 1 个元素。
如果您尝试手动修改映射并在 Address 和 Customer 之间有一个可选的 0:1 关系(而不是 0:N),那么 EF 会有点困惑并开始抛出 IDENTITY 插入异常一些理由。不知道为什么。
因此您可以使用上述映射,并确保在 List<Customers>
已经有功能请求来完全理解双方的独特性方面(我认为转化为一个很好理解的关系代数)。 https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1050579-unique-constraint-i-e-candidate-key-support
public class Customer
{
public int Id { get; set; }
public Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public int? CustomerId { get; set; }
public virtual Customer { get; set; }
}