TPC - 身份主键

时间:2015-04-09 10:19:06

标签: c# entity-framework entity-framework-6.1

我首先使用代码(EntityFramework 6.1)和Table Per Concrete类型方法。

根据此thread的最后一条评论,EF 6.1未在上设置SQL自动增量Identity 。我明白了。

但我想在上强制执行此Identity ,因为我永远不会使用(也不会定义)基类DbSet<>。我不会访问基类集合,只访问具体的集合。

更多的话,一些代码:

public abstract class BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // <- tried to force it, but does not work
    public long Id { get; set; }

    [Timestamp]
    public byte[] DataVersion { get; set; }

    public string CreatedWho { get; set; }
    public DateTime CreatedWhen { get; set; }
    public string UpdatedWho { get; set; }
    public DateTime UpdatedWhen { get; set; }
}

public class Currency : BaseModel
{
    public string IsoCode {get; set; }
}

在我的DbContext课程中有:

public DbSet<Currency> Currencies {get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Enable TPC Inheritance
    modelBuilder.Entity<Currency>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable(typeof(Currency).Name);
        });

    base.OnModelCreating(modelBuilder);
}

使用此代码,在我生成的数据库表Currency中,我按预期拥有所有BaseModel列,Id是主键,确定。但是,尽管使用了明确的Identity属性,但上没有DatabaseGenerated属性集

如何在TPC继承架构中强制Identity

2 个答案:

答案 0 :(得分:1)

标识列是每个表,TPC每个类有一个表,没有共享基类表,它将保存标识生成的id。如果您具有生成标识的具体类型表作为id,则将在这些表中获得重复的ID。

可以找到对此问题的讨论,例如here,此部分涉及此特定问题:

  

如何解决TPC中的身份问题

     

如您所见,使用SQL Server的int标识列并不能正常工作   与TPC一起使用,因为当时会有重复的实体键   在子类表中插入所有具有相同标识种子的表。   因此,要解决这个问题,要么是传播种子(每个表都有)   将需要它自己的初始种子值),或者除了它之外的其他机制   应该使用SQL Server的int标识。其他一些RDBMS有   允许序列(身份)共享的其他机制   使用GUID键可以实现多个表和类似的东西   在SQL Server中。使用GUID键或int身份键时   不同的起始种子将解决问题但另一个   解决方案是完全关闭主键上的身份   属性。因此,我们需要承担提供的责任   将记录插入数据库时​​的唯一键。我们会一起去的   这个解决方案,因为它无论哪个数据库引擎都适用   使用

答案 1 :(得分:0)

似乎[DatabaseGenerated(DatabaseGeneratedOption.Identity)]最终会在TPC inhertiance上下文中强制我的PK上的Identity行为。

诀窍?软件包控制台命令Update-Databse -Force执行自动应用该类别的更改。您需要删除表格以重新创建它们。

我使用以下SQL脚本删除所有内容(甚至__MigrationHistory),灵感来自this blog

WHILE ( EXISTS ( SELECT 1
                 FROM   INFORMATION_SCHEMA.TABLE_CONSTRAINTS
                 WHERE  CONSTRAINT_TYPE = 'FOREIGN KEY' ) )
    BEGIN
        DECLARE @sql NVARCHAR(2000)
        SELECT TOP 1
                @sql = ( 'ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME
                         + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']' )
        FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS
        WHERE   CONSTRAINT_TYPE = 'FOREIGN KEY'
        EXEC (@sql)
        PRINT @sql
    END
GO 

WHILE ( EXISTS ( SELECT 1
                 FROM   INFORMATION_SCHEMA.TABLES ) )
    BEGIN
        DECLARE @sql NVARCHAR(2000)
        SELECT TOP 1
                @sql = ( 'DROP TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME
                         + ']' )
        FROM    INFORMATION_SCHEMA.TABLES

        EXEC (@sql)
        PRINT @sql
    END

之后,重新运行Update-Database -Force命令以重新生成所有表。 Identity将被激活。