1

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

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 上下进行了很多搜索,但没有运气。
  • 我究竟做错了什么?我不明白什么?

在此先感谢,吉姆

4

3 回答 3

4

只需添加通用参数约束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>,这就是为什么在泛型类中需要相同的约束。

于 2013-03-21T21:43:58.727 回答
3

该错误表明您的泛型缺少class约束。在此处阅读有关“类型参数的约束”的信息。

所以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());
    }
}
于 2013-03-21T21:48:01.307 回答
0

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

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

然后,在您的 DbContext 中,覆盖 OnModelCreating 并将映射添加到配置中:

protected override void OnModelCreating(DbModelBuilder builder)
{
   builder.Configurations.Add(new MyEntityConfiguration());
}
于 2013-03-21T21:49:01.447 回答