使用Linq2Sql的时态表

问题描述 投票:0回答:1

我有一个通用的存储库,可以通过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?

我试过的。

  1. 寻找一种方法来配置想要的系统时间 当执行SQL查询时。问题:我找不到一个方法。
  2. 通过一个表值函数暴露查询,允许通过 @validityDate 作为一个参数。问题:我不能用Linq2Sql传递参数(或者至少我没有弄清楚如何传递)。
  3. 创建一个表值函数来执行连接(而不是让EF来做),所以它可以用 context.FromSqlRaw(<query>). 问题:如何创建c#对象树?(由于关系数是1比多,所以返回多行)

我发现的所有使用时序表的例子都使用了 FromSqlRaw. 如果可能的话,我想避免这种情况,因为这意味着整个DB上下文的儿子配置变得毫无用处,而且必须包含额外的映射代码。

c# linq-to-sql entity-framework-core temporal-tables
1个回答
1
投票

我已经找到了解决方案,用 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).

© www.soinside.com 2019 - 2024. All rights reserved.