实体框架4.1 RC:Code First EntityTypeConfiguration继承问题

时间:2011-04-08 11:58:39

标签: c# ef-code-first entity-framework-4.1

我正在尝试使用通用的EntityTypeConfiguration类来为我的所有实体配置主键,以便每个派生的配置类不会重复。我的所有实体都实现了一个公共接口IEntity(它表示每个实体必须具有int类型的Id属性)。

我的配置基类如下所示:

public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>

    where TEntity : class , IEntity {

    public EntityConfiguration() {

        HasKey( e => e.Id );

        Property( e => e.Id ).HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );

    }

}

然后每个实体都拥有自己的特定配置类,如下所示:

public class CustomerConfiguration : EntityConfiguration<Customer> {

    public CustomerConfiguration() : base() {

        // Entity specific configuration here

    }

}

它编译得很好,但我遇到的问题是,在运行时,当EF 4.1 RC尝试创建模型时,我会得到以下异常:

  

System.InvalidOperationException是   未处理的Message =关键组件   'Id'不是声明的属性   输入“客户”。验证它有   未被明确排除在外   模型,它是一个有效的原语   属性。源=的EntityFramework

如果我将CustomerConfiguration类更改为从EntityTypeConfiguration扩展&lt; Customer&gt;并重复主键配置然后它工作正常,但我失去了共享通用配置的能力(DRY主体是动机)。

  • 我在这里做错了吗?
  • 是否有另一种方法可以在实体之间共享通用配置?

此处参考其他课程:

public interface IEntity {

    int Id { get; set; }

}

public class Customer : IEntity {

    public virtual int Id { get; set; }

    public virtual string name { get; set; }

}

谢谢!

4 个答案:

答案 0 :(得分:12)

看起来这些配置在界面方面存在一些问题。如果您将IEntity更改为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()
    {
        ...
    }
}

答案 1 :(得分:2)

我认为你不需要经历所有这些。 EF 4.1 Code First使用了很多约定优于配置,通过这种方式,实体的Id属性被配置为主键。因此,通过在您的实体上实现IEntity接口,您将使用Id作为主键进行设置。

以下是ADO.NET团队博客的链接,该博客解释了主键约定的工作原理 - Conventions for Code First

答案 2 :(得分:1)

您可以在类上创建静态方法并将实体传递给它。例如:

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

答案 3 :(得分:0)

当我拥有带有Id属性的通用抽象类以及抽象成员和自定义属性的实现时,我与EF5.0有类似的问题。 看起来像实体框架代码首先只查找映射的类属性。 我试图使用反射器 - 似乎我是对的,但不确定这是100%。

幸运的是,已找到解决方案:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {                
            modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
            modelBuilder.Entity<MyEntity>()
               .Map(m =>
               {
                   **m.MapInheritedProperties();**                   
               });
        }

所以在我的情况下:要从基类映射属性我必须添加一行代码m.MapInheritedProperties()...