4

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

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使用公共设置器制作:

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

而且(这是一个奇迹!)示例代码运行良好。此外,它在没有基Entity类(当在Id中定义时Order)和私有设置器的情况下也能正常工作。

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

4

2 回答 2

3

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

请参阅相关帖子实体框架代码是否首先支持只读导航属性

于 2012-12-29T10:06:47.923 回答
0

使实体类中的 id 设置器受保护:

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

我试过这个。这将是工作

于 2012-12-29T10:11:23.437 回答