Entity Framework 4.1 RC:Code First EntityTypeConfiguration 继承问题

发布于 2024-10-31 07:55:46 字数 1385 浏览 1 评论 0原文

我尝试使用通用的 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”不是声明的属性 输入“客户”。验证它是否有 没有被明确排除在外 模型并且它是一个有效的原语 财产。来源=EntityFramework

如果我将 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; }

}

谢谢!

I am trying to use a common EntityTypeConfiguration class to configure the primary key for all of my entities, so that each derived configuration class does not repeat itself. All of my entities implement a common interface IEntity (which says that each entity must have an Id property of type int).

My configuration base class looks like this:

public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>

    where TEntity : class , IEntity {

    public EntityConfiguration() {

        HasKey( e => e.Id );

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

    }

}

Each entity then has it's own specific configuration class extending this one like this:

public class CustomerConfiguration : EntityConfiguration<Customer> {

    public CustomerConfiguration() : base() {

        // Entity specific configuration here

    }

}

It compiles fine, but the problem I am having is that at runtime I get the following Exception being raised when EF 4.1 RC tries to create the model:

System.InvalidOperationException was
unhandled Message=The key component
'Id' is not a declared property on
type 'Customer'. Verify that it has
not been explicitly excluded from the
model and that it is a valid primitive
property. Source=EntityFramework

If I change the CustomerConfiguration class to extend from EntityTypeConfiguration<Customer> and repeat the primary key configuration then it works fine, but I lose the ability to share common configuration (DRY principal is the motivation).

  • Am I doing something wrong here?
  • Is there another way to share common configuration between entities?

For reference here are the other classes involved:

public interface IEntity {

    int Id { get; set; }

}

public class Customer : IEntity {

    public virtual int Id { get; set; }

    public virtual string name { get; set; }

}

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江南烟雨〆相思醉 2024-11-07 07:55:46

看起来这些配置在接口上存在一些问题。如果将 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()
    {
        ...
    }
}

It looks like these configurations has some problem with interface. It works if you change IEntity to 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()
    {
        ...
    }
}
情栀口红 2024-11-07 07:55:46

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

以下是 ADO.NET 团队博客的链接,其中解释了主键约定的工作原理 - 代码优先约定

I do not think that you need to go through all of this. EF 4.1 Code First uses a lot of convention over configuration and via this, the Id property of an entity is configured as the primary key. So by implementing the IEntity interface on your entities you are setting them up with the Id as the primary key.

Here is a link to the ADO.NET Team Blog that explains how the primary key convention works - Conventions for Code First

疏忽 2024-11-07 07:55:46

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

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

You could just create a static method on a class and pass the entity into it. For example:

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);
    }
}
最近可好 2024-11-07 07:55:46

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

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

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

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

I have similar issue with EF5.0 when i have generic abstract class with Id property and implementation for abstract members and self defined properties.
look like entity framework code first is looking only for mapped class properties.
i have tried to use reflector - seems i am right, but don't sure about this for 100%.

And, fortunately, have found solution for this:

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

so in my case: to map also properties from base class i have to add one line of code m.MapInheritedProperties()...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文