EF核心方法扩展

时间:2020-04-17 13:43:10

标签: c# .net-core entity-framework-core extension-methods

我要实现的目标是为EFCore构建扩展方法,以首先引入简单的首先检查内存缓存方法。 我的DbContext派生类如下:

  public partial class MyContext : DbContext
  {
    internal readonly IMemoryCache _cache;
    private readonly IDistributedCache _cacheDistributed;

    public MyContext ()
    {
    }

    public MyContext (DbContextOptions<MyContext> options, IMemoryCache memoryCache, IDistributedCache cache)
        : base(options)
    {
      _cache = memoryCache;
      _cacheDistributed = cache;
    } 
    ...
    blah blah blah
    ...
  }

我使用依赖注入来传递我想在我的扩展方法中使用的内存缓存和分布式缓存,如下所示:

  public static class EFCoreExtensions
  {
    internal static IQueryable<TEntity> FromSqlOnQueryable<TEntity>(
      [NotNull] this IQueryable<TEntity> source,
      [NotParameterized] string sql,
      [NotNull] params object[] parameters)
      where TEntity : class
      => throw new NotImplementedException();

    internal static readonly MethodInfo FromSqlOnQueryableMethodInfo
      = typeof(RelationalQueryableExtensions)
        .GetTypeInfo().GetDeclaredMethods(nameof(FromSqlOnQueryable))
        .Single();

    //[StringFormatMethod("sql")]
    public static async Task<List<TEntity>> CachedListFromSqlRawAsync<TEntity>(
    [NotNull] this DbSet<TEntity> source,
    //Microsoft.Extensions.Caching.Memory.IMemoryCache _cache,
    [NotNull] [NotParameterized] string sql,
    [NotNull] params object[] parameters)
    where TEntity : class
    {
      //var infrastructure = source as Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>;
      //var serviceProvider = infrastructure.Instance;
      //var currentDbContext = serviceProvider.GetService(typeof(MyContext)) as MyContext;
      //var _cache = currentDbContext._cache;
      var context = source.GetService<ICurrentDbContext>().Context as MyContext;
      var _cache = context._cache;

      string cache_key = String.Concat(sql, String.Join("-", from o in parameters select (o is null ? "!" : o).ToString()));

      var ret = await _cache.GetOrCreate(cache_key, async entry => {
        entry.AbsoluteExpiration = DateTime.Now.AddMinutes(60);

        var queryableSource = (IQueryable)source;
        var ret = await queryableSource.Provider.CreateQuery<TEntity>(
            Expression.Call(
                null,
                FromSqlOnQueryableMethodInfo.MakeGenericMethod(typeof(TEntity)),
                queryableSource.Expression,
                Expression.Constant(sql),
                Expression.Constant(parameters))).ToListAsync();

        return ret;
      });


      return ret;
    }
  }

但是它不起作用。 context._cache为空

我可以将缓存作为参数传递给该方法,但这看起来不是一个非常优雅的解决方案。

有人知道怎么做吗?

我最初也想过返回一个IQueryable而不是一个List的想法,但是放弃了。如果有人知道该怎么做,我会买几杯饮料。

0 个答案:

没有答案