关键部件'Id'在使用基类和私有setter时,不是类型'TypeName'的声明属性

本文关键字:类型 属性 声明 setter TypeName Id 键部 基类 | 更新日期: 2023-09-27 17:50:17

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

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

由于Id将自动递增,我不希望允许从外部更改此属性。因此,它的setter是private

下面是一个示例实体类型:

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

…配置类型:

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");
    }
}

…和上下文:

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; }
}

现在,当我尝试像这样查询订单时:

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

我得到一个异常:

关键组件'Id'不是类型'Order'的声明属性。确认它没有被显式地排除在模型之外它是一个有效的基本属性。

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

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

并且(这是一个奇迹!)示例代码工作得很好。此外,如果没有基本的Entity类(当IdOrder中定义时)具有私有setter,它也可以正常工作。

逻辑告诉我,这是EF的错误行为。
但是,也许,我遗漏了什么?

关键部件'Id'在使用基类和私有setter时,不是类型'TypeName'的声明属性

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

参见相关文章实体框架代码是否首先支持只读导航属性

在实体类中设置id:

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

我试过了。它将是work