Reputation: 2980
I have several entites that are identical except for the class name that each are mapped to a corresponding identical table. The mapping for each table is similar to the following:
modelBuilder.Entity<Foo>().Map(x =>
{
x.MapInheritedProperties();
x.ToTable("Foo");
})
This approach works, but is repetitive.
I created this class hoping to get rid of the reposition. it is simplified here for brevity.
public class Generic<T>
{
public Generic(DbModelBuilder modelBuilder, string tableName)
{
modelBuilder.Entity<T>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable(tableName);
});
}
}
I get the following compiler error that I do not understand:
The type 'T' must be a reference type in order to use it as parameter 'TEntityType' in the generic type or method 'System.Data.Entity.DbModelBuilder.Entity<TEntityType>()'
Thanks in advance, Jim
Upvotes: 1
Views: 2219
Reputation: 3203
The error states that your generic lacks a class
constraint. Read here about "Constraints on Type Parameters".
So Generic<T>
should be declared as
public class Generic<T> where T: class
{
public Generic(DbModelBuilder modelBuilder, string tableName)
{
modelBuilder.Entity<T>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable(tableName);
});
}
}
But I would suggest using EntityTypeConfiguration. This class will allow you to separate entity mappings from context and implement a kind of inheritance you wanted.
For example:
public abstract class EntityConfiguration<T> : EntityTypeConfiguration<T>
where T : Entity
{
protected EntityConfiguration()
{
ToTable(typeof(T).Name);
// All primary keys are named as <EntityName>Id
Property(e => e.Id)
.HasColumnName(typeof(T).Name + "Id");
}
}
This class states that all entities will have a mapping to table which name is equal to name of the type and every table has an primary key column with name <TableName>Id
.
Then mapping configuration for entity Foo
could be declared as following:
public class FooConfiguration : EntityConfiguration<Foo>
{
public FooConfiguration()
{
Map(m => m.MapInheritedProperties());
// add you mapping logic here
}
}
Then configuration should be registered in DbContext:
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new FooConfiguration());
}
}
Upvotes: 3
Reputation: 17417
EF provides a class that allows you to do this:
class SomeEntityMapping : EntityTypeConfiguration<SomeEntity>
{
public SomeEntityMapping()
{
ToTable("My_Entity");
HasKey(e => e.Id);
//...
}
}
Then, in your DbContext, override OnModelCreating and add the Mappings to the configuration:
protected override void OnModelCreating(DbModelBuilder builder)
{
builder.Configurations.Add(new MyEntityConfiguration());
}
Upvotes: 0
Reputation: 236308
Just add generic parameter constraint where T : class
:
public class Generic<T>
where T : class
{
public Generic(DbModelBuilder modelBuilder, string tableName)
{
modelBuilder.Entity<T>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable(tableName);
});
}
}
Same constraint exist on DbModelBuilder.Entity<T>
method, that's why you need same constraint in your generic class.
Upvotes: 4