将 Entity Framework T4 模板与系统版本时态表一起使用
Using Entity Framework T4 Templates with System-Versioned Temporal Tables
要解决我的错误(如下所示),我想知道如何编辑我的 Entity Framework T4 模板,以便它添加“HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)”到自动生成的 class 的 POCO 配置部分中我的 Temporal Table 的 GENERATED ALWAYS AS ROW START/END 列,如下所示:
Property(x => x.ValidFrom).HasColumnName(@"valid_from").HasColumnType("datetime2").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Property(x => x.ValidTo).HasColumnName(@"valid_to").HasColumnType("datetime2").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
我可以手动添加这个(这解决了我的错误),但是当我保存 T4 模板时它当然被覆盖了。
尝试插入记录时出错:
"Cannot insert an explicit value into a GENERATED ALWAYS column in table 'my_table’. Use INSERT with a column list to exclude the GENERATED ALWAYS column, or insert a DEFAULT into GENERATED ALWAYS column."
我看到了这个post,但是没有用(可能只有在使用edmx文件的时候才有效,或者我没看懂解决方法):
我的时间示例 Table:
CREATE TABLE [dbo].[my_table](
[id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NOT NULL,
[valid_from] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
[valid_to] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_my_table] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([valid_from], [valid_to])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[my_table_history] )
)
GO
ALTER TABLE [dbo].[my_table] ADD CONSTRAINT [DF_my_table_SysStart] DEFAULT (sysutcdatetime()) FOR [valid_from]
GO
ALTER TABLE [dbo].[my_table] ADD CONSTRAINT [DF_my_table_SysEnd] DEFAULT (CONVERT([datetime2](7),'9999-12-31 23:59:59')) FOR [valid_to]
GO
插入记录的示例代码:
var recordToCreate = new MyTable()
{
UserId = info.UserId,
ValidFrom = info.ValidFrom,
ValidTo = info.ValidTo,
};
_context.MyTables.Add(recordToCreate);
_context.SaveChanges();
我明白了。我不得不编辑 EF.Reverse.POCO.Core.ttinclude 文件,将“IsGeneratedAlwaysType”添加到许多 类、方法和 SQL 查询中。我基本上在发现“IsForeignKey”的任何地方都添加了它。我已将添加到每个部分的内容片段粘贴在下方。
public class Column
{
public bool IsGeneratedAlwaysType;
private void SetupConfig()
{
else if (IsGeneratedAlwaysType)
{
if(Settings.UseDataAnnotations)
DataAnnotations.Add("DatabaseGenerated(DatabaseGeneratedOption.Computed)");
else
databaseGeneratedOption = string.Format(".HasDatabaseGeneratedOption({0}DatabaseGeneratedOption.Computed)", schemaReference);
}
private static Column CreateColumn(IDataRecord rdr, Regex rxClean, Table table, Regex columnFilterExclude)
{
var col = new Column
{
IsGeneratedAlwaysType = rdr["IsGeneratedAlwaysType"].ToString().Trim().ToLower() == "true",
private class SqlServerSchemaReader : SchemaReader
{
private const string TableSQL = @"
CAST(CASE WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'GeneratedAlwaysType') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
FROM #Columns c
private const string SynonymTableSQLSetup = @"
CAST(CASE WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(sc.NAME) + '.' + QUOTENAME(o.NAME)), c.NAME, 'GeneratedAlwaysType') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
INTO #SynonymDetails
FROM sys.synonyms sn
INSERT INTO #SynonymDetails (SchemaName, TableName, TableType, Ordinal, ColumnName, IsNullable, TypeName, [MaxLength], [Precision],
[Default], DateTimePrecision, Scale, IsIdentity, IsStoreGenerated, PrimaryKey, PrimaryKeyOrdinal, IsForeignKey, IsGeneratedAlwaysType)
CAST(CASE WHEN COLUMNPROPERTY(st.base_object_id, c.NAME, ''GeneratedAlwaysType'') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
FROM #SynonymTargets st
INNER JOIN sys.columns c
private const string SynonymTableSQL = @"
SELECT SchemaName, TableName, TableType, Ordinal, ColumnName, IsNullable, TypeName, [MaxLength], [Precision],
[Default], DateTimePrecision, Scale, IsIdentity, IsStoreGenerated, PrimaryKey, PrimaryKeyOrdinal, IsForeignKey, IsGeneratedAlwaysType FROM #SynonymDetails";
private const string TableSQLCE = @"
0 as IsGeneratedAlwaysType
FROM INFORMATION_SCHEMA.COLUMNS c
要解决我的错误(如下所示),我想知道如何编辑我的 Entity Framework T4 模板,以便它添加“HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)”到自动生成的 class 的 POCO 配置部分中我的 Temporal Table 的 GENERATED ALWAYS AS ROW START/END 列,如下所示:
Property(x => x.ValidFrom).HasColumnName(@"valid_from").HasColumnType("datetime2").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Property(x => x.ValidTo).HasColumnName(@"valid_to").HasColumnType("datetime2").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
我可以手动添加这个(这解决了我的错误),但是当我保存 T4 模板时它当然被覆盖了。
尝试插入记录时出错: "Cannot insert an explicit value into a GENERATED ALWAYS column in table 'my_table’. Use INSERT with a column list to exclude the GENERATED ALWAYS column, or insert a DEFAULT into GENERATED ALWAYS column."
我看到了这个post,但是没有用(可能只有在使用edmx文件的时候才有效,或者我没看懂解决方法):
我的时间示例 Table:
CREATE TABLE [dbo].[my_table](
[id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NOT NULL,
[valid_from] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
[valid_to] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_my_table] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([valid_from], [valid_to])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[my_table_history] )
)
GO
ALTER TABLE [dbo].[my_table] ADD CONSTRAINT [DF_my_table_SysStart] DEFAULT (sysutcdatetime()) FOR [valid_from]
GO
ALTER TABLE [dbo].[my_table] ADD CONSTRAINT [DF_my_table_SysEnd] DEFAULT (CONVERT([datetime2](7),'9999-12-31 23:59:59')) FOR [valid_to]
GO
插入记录的示例代码:
var recordToCreate = new MyTable()
{
UserId = info.UserId,
ValidFrom = info.ValidFrom,
ValidTo = info.ValidTo,
};
_context.MyTables.Add(recordToCreate);
_context.SaveChanges();
我明白了。我不得不编辑 EF.Reverse.POCO.Core.ttinclude 文件,将“IsGeneratedAlwaysType”添加到许多 类、方法和 SQL 查询中。我基本上在发现“IsForeignKey”的任何地方都添加了它。我已将添加到每个部分的内容片段粘贴在下方。
public class Column
{
public bool IsGeneratedAlwaysType;
private void SetupConfig()
{
else if (IsGeneratedAlwaysType)
{
if(Settings.UseDataAnnotations)
DataAnnotations.Add("DatabaseGenerated(DatabaseGeneratedOption.Computed)");
else
databaseGeneratedOption = string.Format(".HasDatabaseGeneratedOption({0}DatabaseGeneratedOption.Computed)", schemaReference);
}
private static Column CreateColumn(IDataRecord rdr, Regex rxClean, Table table, Regex columnFilterExclude)
{
var col = new Column
{
IsGeneratedAlwaysType = rdr["IsGeneratedAlwaysType"].ToString().Trim().ToLower() == "true",
private class SqlServerSchemaReader : SchemaReader
{
private const string TableSQL = @"
CAST(CASE WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'GeneratedAlwaysType') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
FROM #Columns c
private const string SynonymTableSQLSetup = @"
CAST(CASE WHEN COLUMNPROPERTY(OBJECT_ID(QUOTENAME(sc.NAME) + '.' + QUOTENAME(o.NAME)), c.NAME, 'GeneratedAlwaysType') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
INTO #SynonymDetails
FROM sys.synonyms sn
INSERT INTO #SynonymDetails (SchemaName, TableName, TableType, Ordinal, ColumnName, IsNullable, TypeName, [MaxLength], [Precision],
[Default], DateTimePrecision, Scale, IsIdentity, IsStoreGenerated, PrimaryKey, PrimaryKeyOrdinal, IsForeignKey, IsGeneratedAlwaysType)
CAST(CASE WHEN COLUMNPROPERTY(st.base_object_id, c.NAME, ''GeneratedAlwaysType'') > 0 THEN 1
ELSE 0
END AS BIT) AS IsGeneratedAlwaysType
FROM #SynonymTargets st
INNER JOIN sys.columns c
private const string SynonymTableSQL = @"
SELECT SchemaName, TableName, TableType, Ordinal, ColumnName, IsNullable, TypeName, [MaxLength], [Precision],
[Default], DateTimePrecision, Scale, IsIdentity, IsStoreGenerated, PrimaryKey, PrimaryKeyOrdinal, IsForeignKey, IsGeneratedAlwaysType FROM #SynonymDetails";
private const string TableSQLCE = @"
0 as IsGeneratedAlwaysType
FROM INFORMATION_SCHEMA.COLUMNS c