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?