【问题标题】:How to implement one-to-one relations properly while using soft delete approach in EF Core?在 EF Core 中使用软删除方法时如何正确实现一对一关系?
【发布时间】:2019-11-20 23:01:02
【问题描述】:

我在 EF Core 中使用软删除方法。每个实体都有一个布尔值“Active”。我在实体配置层过滤所有活动实体。

我在软删除一对一关系时遇到问题。问题是,在尝试添加新关系后,我得到 外键约束冲突。因为数据库对软删除一无所知。它只是检查之前是否使用过外键。

我有一个 Customer 模型,它有 一个 Campaign 模型。

场景发生在下面;

  1. 创建客户实例 (Active=true)
  2. 创建一个 Campaign 实例 (Active=true)
  3. 将广告系列设置为客户的广告系列属性
  4. 保存更改
  5. 查询以获取上面保存的客户实体
  6. 访问其 Campaign 导航属性并设置其 Active=false
  7. 保存更改
  8. 查询以获取单个客户实体
  9. 创建一个新的 Campaign 实例 (Active=true)
  10. 将此设置为客户的广告系列属性
  11. 保存更改

第 11 步引发异常,例如“INSERT 语句与 FOREIGN KEY 约束冲突”

模型:

 public class Customer{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool Active { get; set; }
    public Campaign Campaign {get; set;}
    public long CampaignId { get; set; }
 }

 public class Campaign{
    public long Id { get; set; }
    public string Name { get; set; }
    public bool Active { get; set; }
    public Customer Customer {get; set;}
 }

实体配置(根据 IEntityTypeConfiguration 分开):

客户;

modelBuilder.HasKey(a => a.Id);
modelBuilder.HasQueryFilter(a => a.Active);

广告系列;

modelBuilder.HasKey(a => a.Id);
modelBuilder.HasOne(c => c.Customer)
    .WithOne(c => c.Campaign)
    .HasForeignKey<Customer>(c => c.CampaignId)
    .OnDelete(DeleteBehavior.Restrict);
modelBuilder.HasQueryFilter(a => a.Active);

客户表中进行说明;

| Id        | Name       | Active | CampaignId
| --------- |:----------:| ------:| ----------
| 1         | Mark       | 0      | 1         
| 2         | James      | 0      | 1         
| 3         | Henna      | 0      | 1         
| 4         | Yay        | 1      | 1          

我真正需要的是这种一对一的关系。我不想要 2 个具有相同 CampaignId 的活跃客户。在我的业务逻辑中,可以手动或在插入具有相同 CampaignId 的新客户期间软删除客户。

对于这种情况,我应该采取什么方法?

【问题讨论】:

  • 你的表(和表约束)是什么样的?

标签: sql-server entity-framework entity-framework-core ef-core-3.0


【解决方案1】:

在这种情况下,外键不是正确的解决方案。尽管您显然希望能够将其 CampaignId 值编号为 Campaign 1、2、3 等...这些应该是 Campaign Name 属性或复合主键的一部分,而不是任何形式的身份属性。

假设上述情况,我为您的 Campaign 表推荐的主键是 CustomerID 和 CampaignID 的组合。这将始终具有唯一值(只要您确保不为给定客户重复使用广告系列 ID。)

或者,您还可以将表中的 Identity 列作为主键,并将客户的活动 ID 存储为单独的值,该值只是活动的标签。

在重新阅读您的上述请求后,我认为第二种选择最适合您。从 Customer 到 Campaign 的 FK 将使用新的身份字段进行更新。我能看到的最大问题是,按照配置,客户只能有一个活动的活动。如果您需要为每位客户制作多个活动广告系列,则需要从客户表中删除 CampaignID。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-27
    • 2022-01-22
    • 2021-12-29
    • 2019-08-22
    • 2021-07-13
    • 2019-02-07
    • 2017-06-04
    • 1970-01-01
    相关资源
    最近更新 更多