I am trying to use a common EntityTypeConfiguration class to configure the primary key for all of my entities, so that each derived configuration class does not repeat itself. All of my entities implement a common interface IEntity (which says that each entity must have an Id property of type int).
My configuration base class looks like this:
public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : class , IEntity {
public EntityConfiguration() {
HasKey( e => e.Id );
Property( e => e.Id ).HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );
}
}
Each entity then has it's own specific configuration class extending this one like this:
public class CustomerConfiguration : EntityConfiguration<Customer> {
public CustomerConfiguration() : base() {
// Entity specific configuration here
}
}
It compiles fine, but the problem I am having is that at runtime I get the following Exception being raised when EF 4.1 RC tries to create the model:
System.InvalidOperationException was unhandled Message=The key component 'Id' is not a declared property on type 'Customer'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property. Source=EntityFramework
If I change the CustomerConfiguration class to extend from EntityTypeConfiguration<Customer> and repeat the primary key configuration then it works fine, but I lose the ability to share common configuration (DRY principal is the motivation).
For reference here are the other classes involved:
public interface IEntity {
int Id { get; set; }
}
public class Customer : IEntity {
public virtual int Id { get; set; }
public virtual string name { get; set; }
}
Thanks!
It looks like these configurations has some problem with interface. It works if you change IEntity
to EntityBase
:
public class EntityBase
{
public virtual int Id { get; set; }
}
public class Customer : EntityBase
{
public virtual string Name { get; set; }
}
public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : EntityBase
{
public EntityConfiguration()
{
HasKey(e => e.Id);
Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class CustomerConfiguration : EntityConfiguration<Customer>
{
public CustomerConfiguration()
: base()
{
...
}
}
I do not think that you need to go through all of this. EF 4.1 Code First uses a lot of convention over configuration and via this, the Id property of an entity is configured as the primary key. So by implementing the IEntity interface on your entities you are setting them up with the Id as the primary key.
Here is a link to the ADO.NET Team Blog that explains how the primary key convention works - Conventions for Code First
You could just create a static method on a class and pass the entity into it. For example:
public class CustomerConfiguration : EntityConfiguration<Customer>
{
public CustomerConfiguration()
: base()
{
...
EntityConfiguration.Configure(this);
}
}
public static class EntityConfiguration
{
public static void Configure<TEntity>(EntityTypeConfiguration<TEntity> entity) where TEntity : EntityBase
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With