我有一个通用的存储库,可以通过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;
}
}
在配置了实体关系的DbContext之后 导航属性和其他所有实体的属性都被正确加载。
现在我被要求使用 临时SQL表 以便所有实体都有一个有效的范围。
在SQL中,我会加入 FOR SYSTEM_TIME AS OF @validityDate
查询中。
有什么最简单的方法(如果有的话)来调整现有的实现,以便尊重 @validityDate
?
我试过的。
@validityDate
作为一个参数。问题:我不能用Linq2Sql传递参数(或者至少我没有弄清楚如何传递)。context.FromSqlRaw(<query>)
. 问题:如何创建c#对象树?(由于关系数是1比多,所以返回多行)我发现的所有使用时序表的例子都使用了 FromSqlRaw
. 如果可能的话,我想避免这种情况,因为这意味着整个DB上下文的儿子配置变得毫无用处,而且必须包含额外的映射代码。
我已经找到了解决方案,用 efcore-temporal-query (鼻疽)库。
该代码已被修改为使用时序表,正如在《时序表》中描述的那样。README.
仓库方法现在接受一个可选的参数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;
}
其中,历史化查询的相关部分为 query.AsOf(validityDate.Value)
.