Deleting an entity with concurrency in EF Core

c# entity-framework entity-framework-core

Question

I want to delete an entity in EF Core without loading it first from the database. I know similar questions have been asked before, but bear with me, because this case is different. Additional to the usual ID, the entity also has a row version, which is causing problems.

The entity is defined like this:

public int MyEntity {
    public int Id { get; set; }
    //Other irrelevant properties
    public byte[] RowVersion { get; set; }
}

The entity is configured with the fluent API:

class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity> {
    public void Configure( EntityTypeBuilder<MyEntity> builder ) {
        builder.Property( e => e.RowVersion )
            .IsRequired()
            .IsRowVersion();
    }
}

The row version allows me to do optimistic concurrency checking. The problem is that when I try to delete the entity without loading it first like this...

void RemoveMyEntity( int id ) {
    MyEntity removeEntity = new MyEntity {
        Id = id
    };
    m_context.MyEntities.Attach( removeEntity );
    m_context.MyEntities.Remove( removeEntity );
}

...the concurrency check falls on my feet. I get this error message in a DbUpdateConcurrencyException:

Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.

The reason is that EF Core generates this query to delete the item:

exec sp_executesql N'SET NOCOUNT ON;
DELETE FROM [MyEntity]
WHERE [Id] = @p57 AND [RowVersion] IS NULL;
SELECT @@ROWCOUNT',N'@p57 int',@p57=1 -- <--The ID of the item to delete

The issue is clearly in AND [RowVersion] IS NULL. This condition can never be true, since (like I have clearly told EF when configuring the entity), the column is required and hence can not be NULL.

Of course, I have not added a row version in the entity I want to delete and I actually don't want to add the row version, because this would mean I have to get the data from the DB, which is not necessary in this case. I don't even mind concurrency checking here, because it does not hurt if the item was deleted before.

So the question is: Is there a way to ignore concurrency checking for this operation (but not for other operations in the same transaction) or to make the delete work in another way without having to get the row version from the DB first.

1
1
12/21/2017 6:02:46 AM

Popular Answer

Not sure about EF Core but I use the following workaround for EF 6: I have created additional NoConcurencyDbContext which inherits from the main, override OnModelCreating and configure all RowVersion properties to ConcurencyMode.None

publicclass NoConcurencyDbContext : MainDbContext {

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<EntityWithRowVersio>().Property(t => t.RowVersion).IsConcurrencyToken(false);

    }
}

You can write T4 template and generate such context automatically from EF model. So the idea is simple modify model configuration whithin child dbcontext for particular operation. Hope it can be done in EF Core as well

0
3/22/2019 10:45:54 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow