简体   繁体   中英

Entity Framework: Soft Delete and Table per Type

I'm trying to implement the Soft Delete pattern using the following approach: https://stackoverflow.com/a/18985828/213725

However I have difficulties implement it for Table Per Type inheritance. Let's say I have Entity mapped to table "Entity" and its descendant ConcreteEntity mapped to table "ConcreteEntity". I have the IsDeleted column in the table "Entity" to designate whether the entity is "deleted" or not. What I trying to do in OnModelCreating is something like the following:

modelBuilder.Entity<Entity>()
    .Map<Entity>(m =>
    {
        m.ToTable("Entity");
        m.Requires("IsDeleted").HasValue(false);
    })
    .Map<ConcreteEntity>(m =>
    {
        m.ToTable("ConcreteEntity");
    });

I doesn't work though. I'm getting the following error:

(59,10) : error 3032: Problem in mapping fragments starting at lines 59, 142:EntityTypes Entity, ConcreteEntity are being mapped to the same rows in table Entity. Mapping conditions can be used to distinguish the rows that these types are mapped to.

Any ideas what I'm doing wrong?

The soft delete technique uses a discriminator field to ensure that EF always filters out soft deleted entities. But discriminator fields were designed for the purpose of implementing inheritance with Table-Per-Hierarchy. I believe that EF is falling over before it even gets to the ToTable("ConcreteEntity")

That is because EF interprets this line: m.Requires("IsDeleted").HasValue(false); to mean that you are using TPH and an Entity will be retrieved from a single table by adding IsDeleted=false to the sql. I do not believe that EF will let you combine discriminators and Table-Per-Type inheritance.

It turns out the combining TPT and the Soft Delete pattern using the discriminator is quite tricky.

So, in order to make it work, I made Entity abstract and moved IsDeleted column to to the ConcreteEntity table. Then I changed mappings as follows:

modelBuilder.Entity<Entity>().Map(m => m.ToTable("Entity"));

modelBuilder.Entity<ConcreteEntity>().Map(m => 
{
    m.ToTable("ConcreteEntity");
    m.Requires("IsDeleted").HasValue(false);
});

I'm not convinced that it is the best way it can be done, but at least it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM