简体   繁体   English

Net Core:Entity Framework 和 SQL 服务器临时表,自动脚手架

[英]Net Core: Entity Framework and SQL Server Temporal Tables, Automatic Scaffolding

We are having issues using Entity Framework Core 2.2 with SQL Server temporal SystemVersioningTables.我们在使用带有 SQL 服务器临时 SystemVersioningTables 的 Entity Framework Core 2.2 时遇到问题。

The following resolve issues with Entity Framework and system versioning columns.以下解决了 Entity Framework 和系统版本控制列的问题。 entityframework core and sql 2016 temporal tables entityframework 核心和 sql 2016 时态表

Using the solution, is there a way for Entity Framework Core 2.2 to automatically add DatabaseGeneratedOption.Computed or OnModelCreating on SystemVersioning columns?使用该解决方案,Entity Framework Core 2.2 是否可以在 SystemVersioning 列上自动添加DatabaseGeneratedOption.ComputedOnModelCreating

Is there a command parameter in dotnet ef dbcontext scaffold ? dotnet ef dbcontext scaffold中是否有命令参数?

We are seeking a way to automatically add this in, during automatic database scaffolding.我们正在寻找一种在自动数据库脚手架期间自动添加它的方法。 This way, we don't have to manually add this in for all our 1000+ tables, or anytime we add new ones.这样,我们不必为所有 1000 多个表手动添加它,或者在我们添加新表的任何时候。

Company has many databases.公司有很多数据库。

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 

or或者

public partial class DatabaseDBContext : DbContext
{
    partial void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Table1>(entity =>
        {
            entity.Property(e => e.StartTime)
                .ValueGeneratedOnAddOrUpdate();
            entity.Property(e => e.EndTime)
                .ValueGeneratedOnAddOrUpdate();
        });
    }
}

We're using .NET Core 2.2.我们正在使用 .NET Core 2.2。

Note : we do not want to hide the SQL Server columns, given as third solution in article.注意:我们不想隐藏 SQL 服务器列,作为文章中的第三个解决方案。

In OnModelCreating you can examine and modify the model.在 OnModelCreating 中,您可以检查和修改 model。 So this is as easy as:所以这很简单:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    foreach (var et in modelBuilder.Model.GetEntityTypes())
    {
        foreach (var prop in et.GetProperties())
        {
            if (prop.Name == "StartTime"|| prop.Name == "EndTime")
            {
                prop.ValueGenerated = Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.OnAddOrUpdate;
            }
        }
    }
}

This is for EF Core 3.1.这适用于 EF Core 3.1。 EF Core 2.2 is out of support. EF Core 2.2 不受支持。 2.1 is an LTS branch, as is 3.1. 2.1 是 LTS 分支,3.1 也是。 See https://devblogs.microsoft.com/dotnet/net-core-2-2-will-reach-end-of-life-on-december-23-2019/请参阅https://devblogs.microsoft.com/dotnet/net-core-2-2-will-reach-end-of-life-on-december-23-2019/

.NET 6 and Entity Framework Core 6.0 supports SQL Server temporal tables out of the box. .NET 6 和 Entity Framework Core 6.0 支持开箱即用的 SQL 服务器时态表。

Usage:用法:

public class Customer
{
    public Guid Id { get; set; }
    public string Name  { get; set; }

    public List<Order> Orders { get; set; }
}

public class Order
{
    public Guid Id { get; set; }
    public DateTime OrderDate { get; set; }

    public Product Product { get; set; }
    public Customer Customer { get; set; }
}

public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

using IsTemporal:使用 IsTemporal:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Customer>()
        .ToTable("Customers", b => b.IsTemporal());

    modelBuilder
        .Entity<Product>()
        .ToTable("Products", b => b.IsTemporal());

    modelBuilder
        .Entity<Order>()
        .ToTable("Orders", b => b.IsTemporal());
}

Querying historical data:查询历史数据:

var productSnapshots = context.Products
    .TemporalBetween(from, to)
    .OrderBy(product => EF.Property<DateTime>(product, "PeriodStart"))
    .Where(product => product.Name == productName)
    .Select(product =>
        new
        {
            Product = product,
            PeriodStart = EF.Property<DateTime>(product, "PeriodStart"),
            PeriodEnd = EF.Property<DateTime>(product, "PeriodEnd")
        })
    .ToList();

Finding a specific historical record查找特定的历史记录

var order = context.Orders
    .TemporalAsOf(on)
    .Include(e => e.Product)
    .Include(e => e.Customer)
    .Single(order =>
        order.Customer.Name == customerName
        && order.OrderDate > on.Date
        && order.OrderDate < on.Date.AddDays(1));

Restoring deleted data恢复已删除的数据

var customerDeletedOn = context.Customers
    .TemporalAll()
    .Where(customer => customer.Name == customerName)
    .OrderBy(customer => EF.Property<DateTime>(customer, "PeriodEnd"))
    .Select(customer => EF.Property<DateTime>(customer, "PeriodEnd"))
    .Last();

var customerAndOrders = context.Customers
    .TemporalAsOf(customerDeletedOn.AddMilliseconds(-1))
    .Include(e => e.Orders)
    .Single();

context.Add(customerAndOrders);
context.SaveChanges();

Sources:资料来源:

https://devblogs.microsoft.com/dotnet/prime-your-flux-capacitor-sql-server-temporal-tables-in-ef-core-6-0/ https://devblogs.microsoft.com/dotnet/prime-your-flux-capacitor-sql-server-temporal-tables-in-ef-core-6-0/

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/plan https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/plan

https://github.com/dotnet/efcore/issues/4693 https://github.com/dotnet/efcore/issues/4693

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM