【问题标题】:Entity Framework 4.1 RC: Code First EntityTypeConfiguration inheritance issueEntity Framework 4.1 RC:Code First EntityTypeConfiguration 继承问题
【发布时间】:2011-08-01 11:17:50
【问题描述】:

我正在尝试使用一个通用的 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 是 未处理的消息=关键组件 'Id' 不是一个声明的属性 输入“客户”。确认它有 没有被明确排除在 模型并且它是一个有效的原语 财产。来源=实体框架

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

  • 我在这里做错了吗?
  • 还有其他方法可以在实体之间共享通用配置吗?

这里是其他涉及的类供参考:

public interface IEntity {

    int Id { get; set; }

}

public class Customer : IEntity {

    public virtual int Id { get; set; }

    public virtual string name { get; set; }

}

谢谢!

【问题讨论】:

  • 我投票结束这个问题,因为它是关于一个候选版本和一个过时的版本。

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


【解决方案1】:

看起来这些配置的界面有些问题。如果您将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()
    {
        ...
    }
}

【讨论】:

  • 嗯,我试过把接口转换成抽象类,还是不行。然后我将基类设置为非抽象的,但它仍然不起作用!我现在已经开始重复配置,直到(有一天?)Entity Framework 团队支持使用代码优先接口的软件(我认为这是我自己的核心要求)。
  • 基类对我有用,所以肯定有另一个问题。
  • 虽然这对我有用,但我更愿意使用界面。希望 EF 将来会支持这一点。
  • @LadislavMrnka:+1 我在尝试通过通用界面应用RowVersion 配置时遇到了类似的问题,VS2010 EF4.4 上出现相同的错误消息。一旦我将IEntity 更改为EntityBase,它就起作用了。那时它是双向的。使用普通类作为基类,其中 RowVersion 被简单地继承或使用抽象类覆盖 RowVersion。可惜接口方法不起作用。
【解决方案2】:

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

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

【讨论】:

  • 是的,确实如此,但我个人不喜欢依赖约定,并且在可能的情况下,我希望配置显式、自文档化并处于版本控制之下。迟早有些事情可能不符合约定,因此这些问题应该可以预先解决。此简化示例中还没有显示一些共享配置,我不确定约定是否会自动处理。
  • “我不喜欢依赖约定” - 然后编写一个测试,当约定改变时它会失败,记录事实(以代码或其他方式)是一种不太理想的方法
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    而且,幸运的是,已经找到了解决方案:

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

    所以在我的例子中:要映射基类的属性,我必须添加一行代码 m.MapInheritedProperties()...

    【讨论】:

      猜你喜欢
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      • 2012-05-15
      相关资源
      最近更新 更多