The key component "Identifier" is not a declared property of type "TypeName" when the base class and private setter are used

I want to use an abstract base class for entities that does not appear in any table:

public abstract class Entity { public virtual int Id { get; private set; } } 

Since Id will automatically increase, I do not want to allow this property to be changed externally. Therefore, its setter is private .

Here is an example of an object type:

 public class Order : Entity { public virtual string Customer { get; set; } } 

... configuration types:

 public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : Entity { public EntityConfiguration() { HasKey(o => o.Id); Property(o => o.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); } } public class OrderConfiguration : EntityConfiguration<Order> { public OrderConfiguration() { Property(o => o.Customer).HasColumnName("customer"); ToTable("Customers"); } } 

... and context:

 public class Context : DbContext { public Context() : base() { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Configurations.Add(new OrderConfiguration()); } public DbSet<Order> Orders { get; set; } } 

Now when I try to request such orders:

  using (var context = new Context()) { foreach (var order in context.Orders) { Console.WriteLine(order.Customer); } } 

I get an exception:

The key component "Identifier" is not a declared property in the type "Order". Make sure that it has not been explicitly excluded from the model and that it is a valid primitive property.

I read a few questions in SO and found that my approach looks right. Then I changed the base class a bit and made Id with an open setter:

 public abstract class Entity { public virtual int Id { get; set; } } 

And (this is a miracle!) The sample code works fine. Also, it works fine without the Entity base class (when Id is defined in Order ) using a private setter.

Logic tells me that this is the wrong behavior of EF.
But maybe I'm missing something?

+4
source share
2 answers

EF loves access to all the keys. Try using protected so that the assembly can access the identifier, but not the external ones. It seems I need a reasonable question for the EF team.

See related post Is Entity Framework Code First Support for readonly navigation Property

+3
source

make setter id in a protected class of objects:

 public abstract class Entity { public virtual int Id { get; protected set; } } 

I have tried this. it will be work

0
source

All Articles