【问题标题】:Entity Framework - Fluent API Mapping实体框架 - 流畅的 API 映射
【发布时间】:2016-02-26 01:32:09
【问题描述】:
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; }
}

客户必须有一个地址。一个地址可能有也可能没有客户。 Address 中的 Customer 导航属性类似于“可为空”。我在 Customer.AddressId 表中有一个唯一索引。

有什么方法可以使用 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)
)

【问题讨论】:

标签: c# entity-framework ef-fluent-api


【解决方案1】:

我重新创建了整个数据库和模型,并且能够将记录添加到客户和地址表中。

基本上,如果一个客户只能有一个地址,那么这意味着一个地址可以有 0 个或多个客户。 (不是 0 或 1)理想情况下。 但由于您的唯一性限制,地址总是会以 0 或 1 个客户记录结束。但这是一个运行时约束,EF 在设计时并不知道这一点。 (我认为它不能完全掌握 2 路关系的唯一性规则) EF 会将 Address-to-Customer 建模为 0:N,并让运行时处理 N 永远不会超过 1 的事实。

这是因为想到了记录。

  1. customerA 记录,需要有 AddressA 记录
  2. AddressB 记录可以独立插入到 Address 表中。
  3. Customer表中的另一条CustomerC记录必须肯定有Address记录,并且这条记录需要是AddressB或AddressC。 (由于唯一索引约束,它不能是 AddressA)
  4. AddressD 记录可以独立插入到 Address 表中。

所以 AddressA 有 1 条客户记录,AddressD 有 0 条客户记录。

现在的问题是,您的 SQL 服务器知道客户记录只能有一个地址记录,并且该地址记录必须是唯一的。

EF 无法理解双向意义上的唯一性部分。它知道客户只需要一个地址,但不能强制该地址必须是唯一的。如果您尝试插入地址已经属于另一个客户的客户,则当底层 INSERT 引发错误时,自然会发生此错误。由于唯一性约束,EF 实际上在创建模型方面做得很好,客户和地址之间的比例为 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&lt;Customers&gt; 并且它总是会有 0 或 1 个元素。

如果您尝试手动修改映射并且在 Address 和 Customer 之间有一个可选的 0:1 关系(而不是 0:N),那么 EF 会有点困惑并出于某种原因开始抛出 IDENTITY 插入异常。不知道为什么。

这样您就可以使用上述映射,并确保您在 List&lt;Customers&gt; 中始终只有 0 或 1 条记录

已经有功能要求从双方完全理解独特性方面(我认为转化为一个很好理解的关系代数)。 https://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/1050579-unique-constraint-i-e-candidate-key-support

【讨论】:

  • {"当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'Address' 中插入标识列的显式值。"}
  • 我不知道我是否可以清楚地解释这个场景。客户必须有一个强制性的地址。一个地址可能有也可能没有客户。地址中的客户导航属性是“可空的”。我在 Customer.AddressId 表中有一个唯一索引。
  • 您是否编辑了问题以更改客户地址顺序.. 不知道为什么我的答案是倒退的.. 立即尝试
  • @ViniciusGonçalves 能否请您发布两个表的表定义?我会先用 EF 代码设置数据库,然后为你解决这个问题
  • 我编辑了我的问题并添加了定义,tks很多。
【解决方案2】:
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; }
}

【讨论】:

  • 这不是提到的场景。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
相关资源
最近更新 更多