The key component 'Id' is not a declared p

2020-04-08 13:39发布

问题:

I want to use an abstract base class for entities, which is not mapped on any table:

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

Since Id will be auto-increment, I don't want to allow to change this property from outside. Hence, its setter is private.

Here's a sample entity 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'm trying to query orders like this:

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

I'm getting an exception:

The key component 'Id' is not a declared property on type 'Order'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

I've read several questions at SO, and found, that my approach looks correct. Then, I've modified base class a little and made Id with public setter:

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

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

Logic tells me, that is a buggy behavior of EF.
But, may be, I'm missing something?

回答1:

EF likes to access all keys. Try using protected so the assembly can access the ID but externals cant. Seems like a reasonable question for the EF team to me.

See related post Does the Entity Framework code first support readonly navigation property



回答2:

make setter of id in entity class protected :

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

i tried this . it will be work