当使用基类和私有setter时,关键组件“Id”不是“TypeName”类型的声明属性

我想为实体使用抽象基类,它不映射到任何表:

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

由于Id将自动增加,我不想允许从外部更改此属性。 因此,它的二传手是private

这是一个示例实体类型:

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

…配置类型:

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

……和背景:

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

现在,当我试图查询这样的订单时:

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

我得到一个例外:

关键组件“Id”不是“订单”类型的声明属性。 validation它是否未从模型中明确排除,并且它是有效的原始属性。

我在SO上读了几个问题,发现我的方法看起来是正确的。 然后,我稍微修改了基类并使用公共 setter制作了Id

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

而且(这是一个奇迹!)示例代码工作正常。 此外,它没有基本Entity类(当在Order定义Id时)与私有设置器一起正常工作。

逻辑告诉我,这是EF的错误行为。
但是,可能是,我错过了什么?

EF喜欢访问所有密钥。 尝试使用protected,以便程序集可以访问ID,但外部不能。 对于EF团队来说,这似乎是一个合理的问题。

请参阅相关postentity framework代码是否首先支持只读导航属性

在实体类中保护id的setter:

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

我试过这个。 它会起作用