[英]Temporal tables with Linq2Sql
I've got a generic repository to either get en entity by ID or to get all entities:我有一个通用存储库,可以通过 ID 获取实体或获取所有实体:
internal class Repository<TEntity> : IRepository<TEntity>
where TEntity : BaseEntity
{
protected SaiContext Context { get; }
/// <summary>Gets the entity set.</summary>
protected virtual DbSet<TEntity> Set => Context.Set<TEntity>();
public Repository(SaiContext context)
{
Context = context;
}
public async Task<TEntity> GetAsync(int entityId, IEnumerable<string> includeProperties = null)
{
try
{
return await GetQueryableWithIncludes(includeProperties).SingleAsync(entity => entity.Id == entityId);
}
catch (InvalidOperationException)
{
throw new EntityNotFoundException(typeof(TEntity), entityId);
}
}
public async Task<IEnumerable<TEntity>> GetAllAsync(IEnumerable<string> includeProperties = null)
{
return await GetQueryableWithIncludes(includeProperties).ToListAsync();
}
protected IQueryable<TEntity> GetQueryableWithIncludes(IEnumerable<string> includeProperties = null)
{
IQueryable<TEntity> queryable = Set;
if (includeProperties == null)
{
return queryable;
}
foreach (var propertyName in includeProperties)
{
queryable = queryable.Include(propertyName);
}
return queryable;
}
}
After having configured the DbContext for entity relations, navigation properties along with all the rest is being loaded correctly for all entities.在为实体关系配置 DbContext 后,导航属性以及所有 rest 正在为所有实体正确加载。
Now I've been asked to use temporal SQL tables so that all entities have a validity range.现在我被要求使用临时 SQL 表,以便所有实体都有一个有效范围。
With SQL I'd include FOR SYSTEM_TIME AS OF @validityDate
in the query.使用 SQL 我会在查询中包含
FOR SYSTEM_TIME AS OF @validityDate
。
What is the easiest way (if there is any) to adapt the existing implementation in order to respect @validityDate
?调整现有实现以尊重
@validityDate
的最简单方法(如果有的话)是什么?
What I've tried:我试过的:
@validityDate
as a parameter.@validityDate
作为参数传递。 ISSUE: I can't pass the parameter using Linq2Sql (or at least I didn't figurte out how).context.FromSqlRaw(<query>)
.context.FromSqlRaw(<query>)
调用它。 ISSUE: How to create the c# object tree? All examples using temporal tables I've found use FromSqlRaw
.我发现使用时态表的所有示例都使用
FromSqlRaw
。 If possible I'd like to avoid it, as it means that the entire DB context sonfiguration becomes useless and additional code for the mappings has to be included.如果可能的话,我想避免它,因为这意味着整个数据库上下文配置变得无用,并且必须包含映射的附加代码。
I've found the solution with the efcore-temporal-query ( nuget ) library.我找到了efcore-temporal-query ( nuget ) 库的解决方案。
The code has been adapted to use temporal tables as described in the README .该代码已被改编为使用README中描述的临时表。
The repository methods now accept an optional parameter validityDate:存储库方法现在接受可选参数有效性日期:
public async Task<TEntity> GetAsync(int entityId, DateTime? validityDate = null, IEnumerable<string> includeProperties = null)
{
try
{
var query = GetQueryableWithIncludes(includeProperties);
query = GetQueryableWithValidityDate(query, validityDate);
return await query.SingleAsync(entity => entity.Id == entityId);
}
catch (InvalidOperationException)
{
throw new EntityNotFoundException(typeof(TEntity), entityId);
}
}
protected IQueryable<TEntity> GetQueryableWithIncludes(IEnumerable<string> includeProperties = null)
{
IQueryable<TEntity> queryable = Set;
if (includeProperties == null)
{
return queryable;
}
foreach (var propertyName in includeProperties)
{
queryable = queryable.Include(propertyName);
}
return queryable;
}
private static IQueryable<TEntity> GetQueryableWithValidityDate(IQueryable<TEntity> query, DateTime? validityDate)
{
return validityDate.HasValue ? query.AsOf(validityDate.Value) : query;
}
Where te relevant part for the historized query is query.AsOf(validityDate.Value)
.历史查询的相关部分是
query.AsOf(validityDate.Value)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.