我不确定我在这里做错了什么,但我遇到了多重继承和构建模型的问题。我收到错误“属性'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不知道如何处理所有嵌套的基类?
答案 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
)。您可以测试并与实际模型的差异进行比较。必须有一些重要的区别,因为你说你的旧模型有效。我省略了一些标量属性以使示例更简单。
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课上给我一个错误,但问题不在那个课程中。