EF6 中使用复合键的每个具体类型 (TPC) 映射表
Posted
技术标签:
【中文标题】EF6 中使用复合键的每个具体类型 (TPC) 映射表【英文标题】:Table per Concrete Type(TPC) mapping with Composite key in the EF6 【发布时间】:2017-04-07 05:10:36 【问题描述】:我有一个表层次结构,其中包含每个具体类型 (TPC) 映射的表。 (我不确定 [Key, Column] 属性是否必要,但根据https://***.com/a/19792915/959779 它应该可以工作)
类结构:
public abstract class BaseEntity
[Key, Column(Order = 0)]
public int Id get; set;
public class Page: BaseEntity
string Data get; set;
public class PageBackup: Page
[Key, Column(Order = 1)]
public int PageId get; set;
public virtual Page Page get; set;
当Page
和PageBackup
实体的Id
相交时(在向表中添加一些项目后)EF 抛出下一个执行
“EntitySet 'EUICDataContext.Pages' 中的所有对象都必须具有唯一的主键。 但是,“Entities.PageBackup”类型的实例和类型的实例 'Entities.Page' 都具有相同的主键值,'EntitySet=Pages;Id=6'。 "
实体映射代码如下:
class PageMapping : EntityTypeConfiguration<Page>
public PageMapping ()
Map(m => m.ToTable("Page"); );
HasKey(t => t.Id );
class PageBackupMapping : EntityTypeConfiguration<PageBackup>
public PageBackupMapping ()
Map(m =>
m.MapInheritedProperties();
m.ToTable("PageBackup");
);
HasKey(t => new t.Id, t.PageId );
问题是虽然在 EF PageMapping
有复合键 Update-Database
种子脚本创建具有下一个签名的表:
CREATE TABLE [dbo].[PageBackup](
[Id] [int] IDENTITY(1,1) NOT NULL,
[PageId] [int] NOT NULL,
[Data] [nvarchar](max) NULL,
CONSTRAINT [PK_dbo.PageBackup] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
EF 是否允许使用复合键创建表(有很多映射示例,但我没有找到任何关于迁移的信息)?
以及如何代表TPC映射来描述这样的配置?
任何其他解决方案建议都会有所帮助。
【问题讨论】:
【参考方案1】:我正在玩它,看来 EF 6 不支持这种情况。我的迁移使用 Id 主键自动生成。
CreateTable(
"dbo.PageBackUp",
c => new
Id = c.Int(nullable: false),
PageId = c.Int(nullable: false),
)
.PrimaryKey(t => t.Id);
之后,我尝试在 EF Core 1.1.0 上管理这个。在那种情况下我遇到了错误
无法在“页面”上配置键,因为它是派生类型。这 必须在根类型“BaseEntity”上配置密钥。如果你没有 打算将“BaseEntity”包含在模型中,确保它是 未包含在上下文的 DbSet 属性中,在 对 ModelBuilder 的配置调用,或从导航中引用 模型中包含的类型的属性。
我认为这是实体框架的限制。您可以通过此问题向EF repo 提出问题。
我的 EF Core 配置是:
public class ProductContext : DbContext
public ProductContext()
public ProductContext(DbContextOptions<ProductContext> options)
: base(options)
public DbSet<Page> Page get; set;
public DbSet<PageBackup> PageBackup get; set;
protected override void OnConfiguring(DbContextOptionsBuilder builder)
builder.UseSqlServer("Data Source=.\\sqlexpress;");
base.OnConfiguring(builder);
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<Page>()
.HasBaseType<BaseEntity>()
.ToTable("Page")
.HasKey(t => t.Id);
modelBuilder.Entity<PageBackup>()
.HasBaseType<Page>()
.HasKey(t => new t.PageId, t.Id );
base.OnModelCreating(modelBuilder);
EF 6 版本:
public class ProductContext : DbContext
public DbSet<Page> Page get; set;
public DbSet<PageBackup> PageBackup get; set;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<Page>()
.Map(m => m.MapInheritedProperties().ToTable("Page"))
.HasKey(t => t.Id);
modelBuilder.Entity<PageBackup>()
.Map(m => m.MapInheritedProperties().ToTable("PageBackUp"))
.HasKey(t => new t.PageId, t.Id );
base.OnModelCreating(modelBuilder);
【讨论】:
以上是关于EF6 中使用复合键的每个具体类型 (TPC) 映射表的主要内容,如果未能解决你的问题,请参考以下文章
带有 EF 和自动映射器的 OData:无法比较..'。仅支持原始类型、枚举类型和实体类型
在 SqlServer 提供程序清单中找不到存储类型“Varchar(100)”