Net Core:实体框架和 SQL Server 时态表、自动脚手架

Posted

技术标签:

【中文标题】Net Core:实体框架和 SQL Server 时态表、自动脚手架【英文标题】:Net Core: Entity Framework and SQL Server Temporal Tables, Automatic Scaffolding 【发布时间】:2020-10-04 07:46:54 【问题描述】:

我们在使用带有 SQL Server 临时 SystemVersioningTables 的 Entity Framework Core 2.2 时遇到问题。

以下解决了 Entity Framework 和系统版本控制列的问题。 entityframework core and sql 2016 temporal tables

使用该解决方案,Entity Framework Core 2.2 是否有办法在 SystemVersioning 列上自动添加 DatabaseGeneratedOption.ComputedOnModelCreating

dotnet ef dbcontext scaffold中有命令参数吗?

我们正在寻找一种在自动数据库脚手架期间自动添加此功能的方法。这样一来,我们就不必为所有 1000 多个表手动添加它,或者在我们添加新表的任何时候添加。

公司有很多数据库。

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 

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();
        );
    

我们使用的是 .NET Core 2.2。

注意:我们不想隐藏 SQL Server 列,作为文章中的第三个解决方案。

【问题讨论】:

【参考方案1】:

在 OnModelCreating 中,您可以检查和修改模型。所以这很简单:

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;
            
        
    

这适用于 EF Core 3.1。 EF Core 2.2 不受支持。 2.1 是 LTS 分支,3.1 也是。见https://devblogs.microsoft.com/dotnet/net-core-2-2-will-reach-end-of-life-on-december-23-2019/

【讨论】:

太好了,可惜我用的是EF 2.2,你说2.1是LTS分支?你认为他们最终会通过 LTS 将该功能带到 2.2 吗? 2.2 没有修复或增强功能。你可以在 2.2 中做同样的事情。语法可能有点不同。 嗨大卫,也许你可以回答这个问题? ***.com/questions/62445608/… @david-browne-microsoft 为什么是 ValueGenerated.OnAddOrUpdate 而不是 ValueGenerated.OnAdd ?还是两者都做同样的事情?【参考方案2】:

.NET 6 和 Entity Framework Core 6.0 支持开箱即用的 SQL Server 时态表。

用法:

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; 

使用 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());

查询历史数据:

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();

查找特定的历史记录

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));

恢复已删除的数据

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();

来源:

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://github.com/dotnet/efcore/issues/4693

【讨论】:

以上是关于Net Core:实体框架和 SQL Server 时态表、自动脚手架的主要内容,如果未能解决你的问题,请参考以下文章

实体框架、ASP.NET 和 SQL Server CE

使用带有实体框架代码优先和 ASP.NET MVC 3 和 mvc miniprofiler 的 SQL Server CE 时出现问题

带有实体框架和 SQL Server 数据库的 ASP.NET MVC - 图像未显示在视图中......错误显示“无法将“字节”转换为“字符串”

同时将实体框架与 SQL Server 和 SQLite 数据库一起使用

在.NET Core类库中使用EF Core迁移数据库到SQL Server

.NET Core EF框架使用SQL server 2008数据库分页问题:Incorrect syntax near 'OFFSET'. Invalid usage of the