EF 4.1的多重继承问题

时间:2011-08-24 14:49:56

标签: entity-framework-4.1

我不确定我在这里做错了什么,但我遇到了多重继承和构建模型的问题。我收到错误“属性'Id'不是类型的声明属性... ”。在我添加ContextEntity类并且我有一个TPC模型之前,一切正常。每个(非抽象)派生实体都有自己的ID和自己的表。其他类总是存在,我的映射工作正常。这是我的课程:

public abstract class Entity
    {
        public virtual Guid Id { get; set; } 
        public DateTime DateCreated { get; set; }
        public DateTime DateModified { get; set; }
        public EntityStatus EntityStatus { get; set; }
        public byte[] RowVersion { get; set; }
    }


    public abstract class ContextEntity : Entity
    {
        public string Description { get; set; }
        public ICollection<Comment> Comments { get; set; }
        public virtual Contact Owner { get; set; }
    }


    public abstract class Document : ContextEntity
    {

        public virtual Subscription Subscription { get; set; }

    }

    //This is the Class I want as a table
    public class Rfi : Document
    {
        public string Number { get; set; }
        public string Subject { get; set; }

    }

在我拥有ContextEntity之前,我只有Entity。并非所有实体都会使用ContextEntity。我有这个映射文件:

public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
    where TEntity : Entity
    {
        protected EntityConfiguration()
        {
            HasKey(e => e.Id);

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

当我刚刚拥有Entity基类型时,它运行得很好。所以我想我会添加另一个配置映射器:

public class ContextEntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
        where TEntity : ContextEntity
    {
        protected BridgeEntityConfiguration()
        {

            HasKey(e => e.Id);

            Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            Property(e => e.RowVersion).IsRowVersion();
            HasMany(e => e.Comments).WithMany().Map(m =>
                                                        {
                                                            m.MapLeftKey("CommentId");
                                                            m.MapRightKey("EntityId");
                                                            m.ToTable("Entity_Comments");
                                                        });
            HasMany(e => e.Attachments).WithMany().Map(m =>
                                                           {
                                                               m.MapLeftKey("AttachmentId");
                                                               m.MapRightKey("EntityId");
                                                               m.ToTable("Entity_Attachments");
                                                           });
        }
    }

My Derive制图类看起来像这样:

RfiMapping: ContextEntityConfiguration<Rfi>

我猜EF不知道如何处理所有嵌套的基类?

2 个答案:

答案 0 :(得分:0)

您无法从RfiMapping派生ContextEntityConfiguration<Rfi>。这意味着您尝试配置 - 例如 - Id类上的Rfi属性。当添加到模型配置时,它基本上如下所示:

modelBuilder.Entity<Rfi>()
    .HasKey(r => r.Id);
// etc.

Id在基类Entity声明,因此您无法在派生实体上为此类属性定义映射。这就是例外所说的。

如果要在基类属性上定义映射,还必须在映射配置中使用此类:

modelBuilder.Entity<Entity>()
    .HasKey(r => r.Id);
// etc.

我认为从EntityTypeConfiguration<TEntity>派生的通用配置是个坏主意。派生的配置类应始终处理一个特定实体(也可以是抽象实体)并为其定义映射。

因此,您应该具有以下配置:

public class EntityConfiguration : EntityTypeConfiguration<Entity>
public class ContextEntityConfiguration : EntityTypeConfiguration<ContextEntity>
public class DocumentConfiguration : EntityTypeConfiguration<Document>
public class RfiConfiguration : EntityTypeConfiguration<Rfi>

修改

以下示例应用程序显示它也无法使用旧映射(没有ContextEntity)。您可以测试并与实际模型的差异进行比较。必须有一些重要的区别,因为你说你的旧模型有效。我省略了一些标量属性以使示例更简单。

  • 在VS2010中创建新的.NET 4控制台应用程序
  • 添加对EntityFramework.dll
  • 的引用
  • 删除Program.cs的内容并粘贴以下内容
  • 运行应用程序(它会崩溃)

- &GT;

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;

namespace EFWrongMapping
{
    public abstract class Entity
    {
        public virtual Guid Id { get; set; }
        public DateTime DateCreated { get; set; }
        public DateTime DateModified { get; set; }
    }

    public abstract class Document : Entity
    {
        public string Name { get; set; }
    }

    public class Rfi : Document
    {
        public string Number { get; set; }
        public string Subject { get; set; }
    }

    public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
        where TEntity : Entity
    {
        protected EntityConfiguration()
        {
            // The following is not allowed if TEntity is Rfi or generally any other
            // type than Entity (which makes it useless to create a generic configuration)
            HasKey(e => e.Id);
            Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }

    public class RfiMapping : EntityConfiguration<Rfi>
    {
        public RfiMapping()
        {
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<Entity> Entities { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new RfiMapping());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new MyContext())
            {
                // just try to build model and initialize DB
                var initializer = new DropCreateDatabaseIfModelChanges<MyContext>();
                try
                {
                    initializer.InitializeDatabase(context);
                }
                catch (Exception e)
                {
                    // We will land here with exception:
                    // "The property 'Id' is not a declared property on type 'Rfi'"
                    throw;
                }
            }
        }
    }
}

答案 1 :(得分:0)

问题在于我的Document类中的Subscription属性。在那个类中是一个需要无效的属性。一旦我添加了Subscription类的映射并更新了null able属性,一切正常。不知道为什么它在我的Rfi课上给我一个错误,但问题不在那个课程中。