在任何dbContext EF 3.1

时间:2020-03-18 09:52:03

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

最初: 我有几个不同数据库的上下文。它们中的每个都是在特定时间段内的单独数据库。将历史数据与实际数据分开以加快查询速度。

我需要以某种方式统一单个请求的这些上下文。所有请求将像以前一样工作。 为此,我创建了一个本身存储上下文的类,实现了所有Linq方法。在每种方法中,传入的过滤器都将应用于每个上下文中的每个请求。在ToList()之后,我做了SelectMany(x => x)

例如:

位置:

public IFewQueryable<TSource> Where(Expression<Func<TSource, bool>> predicate)
{
    var dictionary = new Dictionary<IQueryable<TSource>, DbContext>();
    foreach (var (query, context) in QueriesToContexts)
    {
        dictionary.Add(query.Where(predicate), context);
    }

    return new FewQueryable<TSource>(dictionary);
}

GroupJoin:

public IFewQueryable<TResult> GroupJoin<TInner, TKey, TResult>(IFewQueryable<TInner> inner, Expression<Func<TSource, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TSource, IEnumerable<TInner>, TResult>> resultSelector) 
            where TResult : class 
            where TInner : class
{
    var dictionary = new Dictionary<IQueryable<TResult>, DbContext>();
    var innerCasted = inner as FewQueryable<TInner>;

    for (var i = 0; i < QueriesToContexts.Count; i++)
    {
        var (queryOriginal, contextOriginal) = QueriesToContexts.Skip(i).First();

        dictionary.Add(queryOriginal.GroupJoin(contextOriginal.Set<TInner>(), outerKeySelector, innerKeySelector, resultSelector), contextOriginal);
    }

    return new FewQueryable<TResult>(dictionary);
}

我有一个问题。在核心3.1中,Union可以在SQL Server上运行,因此我尝试使用impl Union方法。 但通常情况下,Union包含由其他查询组成的查询,因此我无法再使用:

contextOriginal.Set<TInner>()

但是我需要以某种方式在一个上下文中执行请求。 在EF版本6和更早的版本中,可以更改执行上下文,但是据我所知,在EF内核中,没有。所以我尝试通过Expression来做到这一点:

public IFewQueryable<TSource> Union(IQueryable<TSource> inner)
{
    var dictionary = new Dictionary<IQueryable<TSource>, DbContext>();

    foreach (var (query, context) in QueriesToContexts)
    {
        var expression = ConvertQuery(inner.Expression as MethodCallExpression, context);
        var newQuery = query.Union(query.Provider.CreateQuery<TSource>(expression));

        dictionary.Add(query.Union(newQuery), context);
    }

    return new FewQueryable<TSource>(dictionary);
}

private MethodCallExpression ConvertQuery(MethodCallExpression expression, DbContext context)
{
    var args = new Expression[expression.Arguments.Count];
    expression.Arguments.CopyTo(args, 0);

    for (var i = 0; i<args.Length; i++)
    {
        if (args[i].GetType().BaseType == typeof(MethodCallExpression))
        {
            args[i] = ConvertQuery(args[i] as MethodCallExpression, context);
        }

        if (args[i].GetType() == typeof(ConstantExpression))
        {
            var castedExpression = args[i] as ConstantExpression;

            var setMethod = typeof(DbContext).GetMethod("Set").MakeGenericMethod(castedExpression.Type.GenericTypeArguments[0]);
            var valueDbSet = setMethod.Invoke(context, null);

            var asQueryable = typeof(System.Linq.Queryable).GetMethods().Where(x => x.Name == "AsQueryable")
                .ToList()[0].MakeGenericMethod(castedExpression.Type.GenericTypeArguments[0]);
            var casted = asQueryable.Invoke(null, new[] {valueDbSet });
            var constant = Expression.Constant(casted);

            args[i] = constant;
        }
    }
}

但是我得到了例外:

{{query}}  by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information.
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
       at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
       at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
       at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
       at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
       at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
       at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
       at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
       at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
       at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

0 个答案:

没有答案
相关问题