cSt*_*off 20 c# sql entity-framework temporal sql-server-2016
我可以在SQL Server 2016中使用时态表.遗憾的是,Entity Framework 6还不知道这个功能.是否有可能使用实体框架6 使用新的查询选项(请参阅msdn)?
我创建了一个带有员工时态表的简单演示项目:
我使用edmx将表映射到实体(感谢Matt Ruwe):
使用纯sql语句一切正常:
using (var context = new TemporalEntities())
{
var employee = context.Employees.Single(e => e.EmployeeID == 2);
var query =
$@"SELECT * FROM [TemporalTest].[dbo].[{nameof(Employee)}]
FOR SYSTEM_TIME BETWEEN
'0001-01-01 00:00:00.00' AND '{employee.ValidTo:O}'
WHERE EmployeeID = 2";
var historyOfEmployee = context.Employees.SqlQuery(query).ToList();
}
Run Code Online (Sandbox Code Playgroud)
是否可以在没有纯SQL的情况下将历史记录功能添加到每个实体?我的解决方案作为实体扩展与反射来操纵SQL查询IQuerable并不完美.是否有现有的扩展或库来执行此操作?
编辑:(基于Pawel的评论)
我试图使用表值函数:
CREATE FUNCTION dbo.GetEmployeeHistory(
@EmployeeID int,
@startTime datetime2,
@endTime datetime2)
RETURNS TABLE
AS
RETURN
(
SELECT
EmployeeID,
[Name],
Position,
Department,
[Address],
ValidFrom,
ValidTo
FROM dbo.Employee
FOR SYSTEM_TIME BETWEEN @startTime AND @endTime
WHERE EmployeeID = @EmployeeID
);
Run Code Online (Sandbox Code Playgroud)
using (var context = new TemporalEntities())
{
var employee = context.Employees.Single(e => e.EmployeeID == 2);
var historyOfEmployee =
context.GetEmployeeHistory(2, DateTime.MinValue, employee.ValidTo).ToList();
}
Run Code Online (Sandbox Code Playgroud)
我是否必须为每个实体创建一个函数,或者是否有通用选项?
此处添加了对时态表的初始支持:e7c0b9d(模型/元数据部分)和此处的4b25a88(查询部分),并将在下一个预览版(预览版 8)以及当前的每晚位中提供。
用法:
将实体映射到时态表可以在 OnModelCreating 中完成,如下所示:
modelBuilder.Entity<MyTemporalEntity>().ToTable(tb => tb.IsTemporal());
Run Code Online (Sandbox Code Playgroud)
还支持其他配置 - 历史表名称/模式、周期开始和周期结束列的名称
modelBuilder.Entity<MyTemporalEntity>().ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.HasPeriodStart("SystemTimeStart");
ttb.HasPeriodEnd("SystemTimeEnd");
ttb.WithHistoryTable("MyHistoryTable", "mySchema");
}));
Run Code Online (Sandbox Code Playgroud)
支持迁移,因此现有实体可以转换为时间实体。
查询:
var myDate = new DateTime(2020, 1, 1);
context.MyTemporalEntities.TemporalAsOf(myDate).Where(e => e.Id < 10);
Run Code Online (Sandbox Code Playgroud)
支持的操作:TemporalAsOf、TemporalAll、TemporalBetween、TemporalFromTo、TemporalContainedIn。
一些限制和注意事项
使用临时操作的查询始终标记为“NoTracking”。此类查询可能会返回具有相同密钥的多个实体,否则 EF 将无法正确解析它们的身份。
直接支持时态操作DbSet,而不是IQueryable. 如果是继承,则不能应用于OfType操作。相反,使用:
context.Set<MyDerivedEntity>().TemporalAsOf(...);
Run Code Online (Sandbox Code Playgroud)
导航扩展仅支持AsOf操作,因为它是保证结果图一致性的唯一时间操作。对于其他时间操作,必须使用手动创建导航Join。
扩展导航时,目标实体还必须映射到时态表。时间操作从源传播到目标。不支持从时间实体导航到非时间实体。
context.Customers.TemporalAsOf(new DateTime(2020, 1, 1)).Select(c => c.Orders)
Run Code Online (Sandbox Code Playgroud)
自 2020 年 1 月 1 日起,将退回客户及其订单。临时操作会自动应用于客户和订单。
引自莫马尔
| 归档时间: |
|
| 查看次数: |
3956 次 |
| 最近记录: |