Created
February 15, 2022 06:26
-
-
Save danielplawgo/d54cf779062bcddac36b72b600201326 to your computer and use it in GitHub Desktop.
EF Core 6 Temporal Tables
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public partial class AddProducts : Migration | |
{ | |
protected override void Up(MigrationBuilder migrationBuilder) | |
{ | |
migrationBuilder.CreateTable( | |
name: "Products", | |
columns: table => new | |
{ | |
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |
Name = table.Column<string>(type: "nvarchar(max)", nullable: false), | |
Description = table.Column<string>(type: "nvarchar(max)", nullable: false), | |
PeriodEnd = table.Column<DateTime>(type: "datetime2", nullable: false) | |
.Annotation("SqlServer:IsTemporal", true) | |
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd") | |
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart"), | |
PeriodStart = table.Column<DateTime>(type: "datetime2", nullable: false) | |
.Annotation("SqlServer:IsTemporal", true) | |
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd") | |
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart") | |
}, | |
constraints: table => | |
{ | |
table.PrimaryKey("PK_Products", x => x.Id); | |
}) | |
.Annotation("SqlServer:IsTemporal", true) | |
.Annotation("SqlServer:TemporalHistoryTableName", "ProductsHistory") | |
.Annotation("SqlServer:TemporalHistoryTableSchema", null) | |
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd") | |
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart"); | |
} | |
protected override void Down(MigrationBuilder migrationBuilder) | |
{ | |
migrationBuilder.DropTable( | |
name: "Products") | |
.Annotation("SqlServer:IsTemporal", true) | |
.Annotation("SqlServer:TemporalHistoryTableName", "ProductsHistory") | |
.Annotation("SqlServer:TemporalHistoryTableSchema", null) | |
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd") | |
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DataContext : DbContext | |
{ | |
public DbSet<Product> Products { get; set; } | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
base.OnModelCreating(modelBuilder); | |
modelBuilder.Entity<Product>() | |
.ToTable("Products", b => b.IsTemporal()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static async Task DisplayHistoryWithDates(Guid id) | |
{ | |
await using DataContext db = new DataContext(); | |
var historyItems = await db.Products | |
.TemporalAll() | |
.Where(p => p.Id == id) | |
.Select(p => new | |
{ | |
p.Name, | |
p.Description, | |
PeriodStart = EF.Property<DateTime>(p, "PeriodStart"), | |
PeriodEnd = EF.Property<DateTime>(p, "PeriodEnd") | |
}) | |
.ToListAsync(); | |
foreach (var item in historyItems) | |
{ | |
Console.WriteLine($"{item.Name}: {item.Description}, Start: {item.PeriodStart}, End: {item.PeriodEnd}"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
exec sp_executesql N'SELECT [p].[Name], [p].[Description], [p].[PeriodStart], [p].[PeriodEnd] | |
FROM [Products] FOR SYSTEM_TIME ALL AS [p] | |
WHERE [p].[Id] = @__id_0',N'@__id_0 uniqueidentifier',@__id_0='DD2E351A-25B6-4638-8FD0-EE40F82C57E3' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Product | |
{ | |
public Guid Id { get; set; } | |
public string Name { get; set; } | |
public string Description { get; set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var id = await CreateProduct(); | |
await UpdateProduct(id); | |
await RemoveProduct(id); | |
static async Task<Guid> CreateProduct() | |
{ | |
await using DataContext db = new DataContext(); | |
var product = new Product() | |
{ | |
Id = Guid.NewGuid(), | |
Name = "product name", | |
Description = "product description" | |
}; | |
await db.Products.AddAsync(product); | |
await db.SaveChangesAsync(); | |
return product.Id; | |
} | |
static async Task UpdateProduct(Guid id) | |
{ | |
await using DataContext db = new DataContext(); | |
var product = await db.Products.FirstAsync(p => p.Id == id); | |
product.Name = "new product name"; | |
await db.SaveChangesAsync(); | |
} | |
static async Task RemoveProduct(Guid id) | |
{ | |
await using DataContext db = new DataContext(); | |
var product = await db.Products.FirstAsync(p => p.Id == id); | |
db.Products.Remove(product); | |
await db.SaveChangesAsync(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment