Entity Framework generic entity inheritance id error

c# entity-framework entity-framework-core inheritance


Part 2 problem, which continues from here: EntityFramework Core - Update record fails with DbUpdateConcurrencyException


The derived type 'BinaryFile' cannot have KeyAttribute on property 'Id' since primary key can only be declared on the root type.

I am trying to make inheritance for my entities as much as possible, so I remove duplication as much as possible.

My inheritance structure:

public interface IEntityMinimum
    bool IsDeleted { get; set; }
    byte[] Version { get; set; }
    string CreatedBy { get; set; }

public class EntityMinimum : IEntityMinimum
    public bool IsDeleted { get; set; }
    public byte[] Version { get; set; }
    public string CreatedBy { get; set; }

public interface IEntity : IEntityMinimum
    object Id { get; set; }
    DateTime CreatedDate { get; set; }
    DateTime? ModifiedDate { get; set; }
    string ModifiedBy { get; set; }

public interface IEntity<T> : IEntity
    new T Id { get; set; }

public abstract class Entity<T> : EntityMinimum, IEntity<T> 
    public T Id { get; set; }

    object IEntity.Id
        get => Id;
        set => throw new NotImplementedException();

    private DateTime? _createdDate;
    public DateTime CreatedDate
        get => _createdDate ?? DateTime.UtcNow;
        set => _createdDate = value;

    public DateTime? ModifiedDate { get; set; }

    public string ModifiedBy { get; set; }

public class EntityMaximum : Entity<int>
    public bool IsActive { get; set; }

public class BinaryFile : EntityMaximum
    public string Name { get; set; }
    public string UniqueName { get; set; }
    public Guid UniqueId { get; set; }
    public byte[] Content { get; set; }

    public virtual ICollection<Campaign> Campaigns { get; set; }

I get this error when I use Fluent API to disable isConcurrencyToken on the Version field for the EntityMinimum class like this:

    // https://stackoverflow.com/questions/44009020/entity-framework-isrowversion-without-concurrency-check
    builder.Entity<EntityMinimum>().Property(x => x.Version).IsRowVersion().IsConcurrencyToken(false);

This is required because I had another issue if I do not disable isConcurrencyToken on the Version field:

Microsoft.EntityFrameworkCore.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.

If I remove fluent api configuration, it works, but doesn't update because of Version field which has [TimeStamp] attribute.

I have this [TimeStamp] Version field in EntityMinimum to append Version to every table, so I can use TimeStamp for synchronisation purposes between mobile and web data.

Am I doing this structure correctly, or should I get rid of [TimeStamp] byte[] Version and just use string Version and save DateTime ticks into it for synchronisation purpose?

6/2/2017 10:03:42 AM

Accepted Answer

The problem is that the call


marks the EntityMinimum class as entity (part of the EF Core inheritance strategy), while as I understand, you use the base class hierarchy just for implementation purposes.

Instead, you could use the EF Core model metadata services to turn off IsConcurrencyToken for the Version property of any real entity derived from EntityMinimum like this:

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    if (typeof(EntityMinimum).IsAssignableFrom(entityType.ClrType))
        entityType.FindProperty("Version").IsConcurrencyToken = false;
6/2/2017 11:20:53 AM

Related Questions


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