TPC - 身份主键
TPC - Identity primary key
我首先使用代码 (EntityFramework 6.1) 和 Table 每个具体类型的方法。
根据这个 thread 的最后一条评论,EF 6.1 没有设置 SQL 自动递增 Identity
on。我明白了。
但我想在上强制使用Identity
,因为我永远不会使用(也不会定义)基础class DbSet<>
。我不会访问基础 class 集合,只会访问具体的集合。
更多的文字,一些代码:
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
class 中有:
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);
}
使用此代码,在我生成的数据库 Table Currency
中,我拥有预期的所有 BaseModel
列,Id
是主键,好的。但是它没有 Identity
属性 设置 on,尽管使用了明确的 DatabaseGenerated
属性。
如何在 TPC 继承架构中强制 Identity
?
标识列是每个 table,使用 TPC 你有一个 table 每个 class,并且没有共享基础 class table身份生成的 id。如果您有具体类型 table 生成标识作为 id,您将在这些 table 中获得重复的 id。
可以找到关于此问题的讨论,例如here,这部分涵盖了这个具体问题:
How to Solve The Identity Problem in TPC
As you saw, using SQL Server’s int identity columns doesn't work very
well together with TPC since there will be duplicate entity keys when
inserting in subclasses tables with all having the same identity seed.
Therefore, to solve this, either a spread seed (where each table has
its own initial seed value) will be needed, or a mechanism other than
SQL Server’s int identity should be used. Some other RDBMSes have
other mechanisms allowing a sequence (identity) to be shared by
multiple tables, and something similar can be achieved with GUID keys
in SQL Server. While using GUID keys, or int identity keys with
different starting seeds will solve the problem but yet another
solution would be to completely switch off identity on the primary key
property. As a result, we need to take the responsibility of providing
unique keys when inserting records to the database. We will go with
this solution since it works regardless of which database engine is
used.
看来 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
终于可以在 TPC 继承上下文中强制我的 PK 上的身份行为。
诀窍?程序包控制台命令 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
将被激活。
我首先使用代码 (EntityFramework 6.1) 和 Table 每个具体类型的方法。
根据这个 thread 的最后一条评论,EF 6.1 没有设置 SQL 自动递增 Identity
on。我明白了。
但我想在上强制使用Identity
,因为我永远不会使用(也不会定义)基础class DbSet<>
。我不会访问基础 class 集合,只会访问具体的集合。
更多的文字,一些代码:
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
class 中有:
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);
}
使用此代码,在我生成的数据库 Table Currency
中,我拥有预期的所有 BaseModel
列,Id
是主键,好的。但是它没有 Identity
属性 设置 on,尽管使用了明确的 DatabaseGenerated
属性。
如何在 TPC 继承架构中强制 Identity
?
标识列是每个 table,使用 TPC 你有一个 table 每个 class,并且没有共享基础 class table身份生成的 id。如果您有具体类型 table 生成标识作为 id,您将在这些 table 中获得重复的 id。
可以找到关于此问题的讨论,例如here,这部分涵盖了这个具体问题:
How to Solve The Identity Problem in TPC
As you saw, using SQL Server’s int identity columns doesn't work very well together with TPC since there will be duplicate entity keys when inserting in subclasses tables with all having the same identity seed. Therefore, to solve this, either a spread seed (where each table has its own initial seed value) will be needed, or a mechanism other than SQL Server’s int identity should be used. Some other RDBMSes have other mechanisms allowing a sequence (identity) to be shared by multiple tables, and something similar can be achieved with GUID keys in SQL Server. While using GUID keys, or int identity keys with different starting seeds will solve the problem but yet another solution would be to completely switch off identity on the primary key property. As a result, we need to take the responsibility of providing unique keys when inserting records to the database. We will go with this solution since it works regardless of which database engine is used.
看来 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
终于可以在 TPC 继承上下文中强制我的 PK 上的身份行为。
诀窍?程序包控制台命令 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
将被激活。