Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Rather than augmenting existing SQL it might make more sense to create new operations.
- // E.g. MakeTemporal after CreateTable and DropTemporal before DropTable. Not sure how to cause that to happen for now.
- public class TemporalSqlServerMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
- {
- // HACK: I gave up. This is required to explicitly name history tables and I dont know how to get the target schema from this code.
- private const string DefaultSchema = "dbo";
- public TemporalSqlServerMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider migrationsAnnotations)
- : base(dependencies, migrationsAnnotations) { }
- protected override void ColumnDefinition(AddColumnOperation operation, IModel model, MigrationCommandListBuilder builder)
- {
- DisallowNullablePeriodColumns(operation);
- base.ColumnDefinition(operation, model, builder);
- }
- protected override void Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder)
- {
- DisallowNullablePeriodColumns(operation);
- base.Generate(operation, model, builder);
- }
- protected override void Generate(DropColumnOperation operation, IModel model, MigrationCommandListBuilder builder)
- {
- var temporalAnnotation = operation[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?;
- var isPeriodStart = temporalAnnotation == TemporalComponentType.PeriodStart;
- var isPeriodEnd = temporalAnnotation == TemporalComponentType.PeriodEnd;
- if (isPeriodStart || isPeriodEnd)
- {
- // Period columns cant be dropped
- throw new InvalidOperationException("Period Columns cannot be dropped");
- }
- base.Generate(operation, model, builder);
- }
- protected override void Generate(CreateTableOperation operation, IModel model, MigrationCommandListBuilder builder)
- {
- base.Generate(operation, model, builder);
- var temporalAnnotation = operation[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?;
- var isTemporal = temporalAnnotation == TemporalComponentType.Table;
- if (isTemporal)
- {
- var tableName = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema ?? DefaultSchema);
- var periodStartColumn = operation.Columns.Single(c => (c[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?) == TemporalComponentType.PeriodStart);
- var periodEndColumn = operation.Columns.Single(c => (c[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?) == TemporalComponentType.PeriodEnd);
- var fqPeriodStartColumnName = Dependencies.SqlGenerationHelper.DelimitIdentifier(periodStartColumn.Name);
- var fqPeriodEndColumnName = Dependencies.SqlGenerationHelper.DelimitIdentifier(periodEndColumn.Name);
- builder
- .Append($"ALTER TABLE {tableName} ADD PERIOD FOR SYSTEM_TIME ({fqPeriodStartColumnName}, {fqPeriodEndColumnName})")
- .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
- //TODO: Decide whether we care to make period columns hidden
- builder
- .Append($"ALTER TABLE {tableName} ALTER COLUMN {fqPeriodStartColumnName} ADD HIDDEN")
- .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator)
- .Append($"ALTER TABLE {tableName} ALTER COLUMN {fqPeriodEndColumnName} ADD HIDDEN")
- .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
- //TODO: Do we want to allow custom table suffixes? Use generated history table name?
- var historyTableName = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name + "_History", operation.Schema ?? DefaultSchema);
- builder
- .Append($"ALTER TABLE {tableName} SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = {historyTableName}))")
- .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
- EndStatement(builder);
- }
- }
- protected override void Generate(DropTableOperation operation, IModel model, MigrationCommandListBuilder builder)
- {
- // Cannot drop a System-versioned table so we have to disable it first
- var temporalAnnotation = operation[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?;
- var isTemporal = temporalAnnotation == TemporalComponentType.Table;
- if (isTemporal)
- {
- var fullTableName = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema ?? DefaultSchema);
- builder
- .Append($"ALTER TABLE {fullTableName} SET (SYSTEM_VERSIONING = OFF)")
- .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
- builder.AppendLine();
- }
- base.Generate(operation, model, builder);
- }
- private void DisallowNullablePeriodColumns(ColumnOperation operation)
- {
- var temporalAnnotation = operation[TemporalAnnotationNames.TemporalComponent] as TemporalComponentType?;
- var isPeriodStart = temporalAnnotation == TemporalComponentType.PeriodStart;
- var isPeriodEnd = temporalAnnotation == TemporalComponentType.PeriodEnd;
- if (isPeriodStart || isPeriodEnd)
- {
- // Period columns cant be nullable
- if (operation.IsNullable)
- {
- throw new InvalidOperationException("Period Columns cannot be nullable");
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement