我正在尝试使用通用的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; }
}
谢谢!
答案 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()...