无法使用泛型首先创建EF代码映射类

时间:2013-03-21 21:37:09

标签: entity-framework ef-code-first entity-framework-5

除了每个映射到相应的相同表的类名之外,我有几个相同的entite。每个表的映射类似于以下内容:

modelBuilder.Entity<Foo>().Map(x =>
{
  x.MapInheritedProperties();
  x.ToTable("Foo");
})

这种方法有效,但重复。

我创建了这个类,希望摆脱重新定位。为简洁起见,这里简化了。

public class Generic<T>
{
    public Generic(DbModelBuilder modelBuilder, string tableName)
    {
        modelBuilder.Entity<T>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable(tableName);
        });
    }
}

我得到以下编译错误,我不明白:

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>()'
  • 像许多.Net编码器一样,我经常使用泛型,但不经常写它们。
  • 我已经使用了EF一段时间了,但我对Code First
  • 很新
  • 我做了很多搜索和关闭SO而没有运气。
  • 我做错了什么?我不明白什么?

提前致谢, 吉姆

3 个答案:

答案 0 :(得分:3)

只需添加通用参数约束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);
        });
    }
}

DbModelBuilder.Entity<T>方法存在相同的约束,这就是您在泛型类中需要相同约束的原因。

答案 1 :(得分:3)

错误表明您的通用缺少class约束。 Read here关于“类型参数的约束”。

因此Generic<T>应声明为

public class Generic<T> where T: class
{
    public Generic(DbModelBuilder modelBuilder, string tableName)
    {
        modelBuilder.Entity<T>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable(tableName);
        });
    }
}

但我建议使用EntityTypeConfiguration。这个类允许你将实体映射与上下文分开,并实现一种你想要的继承。

例如:

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");
    }
}

此类声明所有实体都将具有映射到表的名称,该名称等于该类型的名称,并且每个表都具有名为<TableName>Id的主键列。

然后可以将实体Foo的映射配置声明如下:

public class FooConfiguration : EntityConfiguration<Foo>
{
    public FooConfiguration()
    {
        Map(m => m.MapInheritedProperties());
        // add you mapping logic here
    }
}

然后配置应该在DbContext中注册:

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new FooConfiguration());
    }
}

答案 2 :(得分:0)

EF提供了一个允许您执行此操作的类:

class SomeEntityMapping : EntityTypeConfiguration<SomeEntity>
{
    public SomeEntityMapping()
    {
        ToTable("My_Entity");
        HasKey(e => e.Id);
        //...
    }
} 

然后,在您的DbContext中,重写OnModelCreating并将Mappings添加到配置中:

protected override void OnModelCreating(DbModelBuilder builder)
{
   builder.Configurations.Add(new MyEntityConfiguration());
}