I am using the soft delete methodology in EF Core. Every entity has a boolean "Active". I filter all Active entities in the entity configuration layer.
I encountered a problem when soft deleting one-to-one relation. The problem is, I get foreign key constraint conflict after trying to add a new relationship. Because the database does not know anything about the soft deletion. It just checks if the foreign key used before or not.
I have a Customer model which has one Campaign model.
The scenario happens in the following;
- Create a Customer instance (Active=true)
- Create a Campaign instance (Active=true)
- Set Campaign to Customer's Campaign property
- SaveChanges
- Query to get Customer entity saved above
- Access its Campaign navigation property and set its Active=false
- SaveChanges
- Query to get single Customer entity
- Create a new Campaign instance (Active=true)
- Set this to Customer's Campaign property
- SaveChanges
Step 11 throws an exception like "The INSERT statement conflicted with the FOREIGN KEY constraint"
The Models:
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;}
}
Entity Configurations(Separated based on IEntityTypeConfiguration):
Customer;
modelBuilder.HasKey(a => a.Id);
modelBuilder.HasQueryFilter(a => a.Active);
Campaign;
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);
To illustrate it in Customers table;
| Id | Name | Active | CampaignId
| --------- |:----------:| ------:| ----------
| 1 | Mark | 0 | 1
| 2 | James | 0 | 1
| 3 | Henna | 0 | 1
| 4 | Yay | 1 | 1
What I really need is this kind of one-to-one relation. I don't want 2 active customers with the same CampaignId. In my business logic, customers can be soft-deleted either manually or during an insert for a new customer with the same CampaignId.
What approach should I follow for a situation like this?