Entityframework忽略包含在自定义构建的表达式

时间:2018-02-15 19:53:20

标签: c# entity-framework iqueryable queryinterceptor

目前我正在开发一个项目,该项目在Entityframework之上构建了一个额外的层,用于将查询从实体转换为DTO。我们使用自定义可查询来抽象表达式创建,以在实现之前调用convert。

public Expression ConvertExpression(Expression origExpression)
{
    var expandedExpression = ExpressionExtensions.Expand(origExpression);
    var dummyValueExpr = expandedExpression as ConstantExpression;
    if (null != dummyValueExpr)
    {
        // Check if the expression is actually a dummy marker for some wrapper queryable
        var dummyQueryableValueConstant = dummyValueExpr.Value as IDummyQueryableValueConstant;
        if (null == dummyQueryableValueConstant)
        {
            // It's possible that the constant value is also another ConvertedQueryable.
            var innerQueryable = dummyValueExpr.Value as IConvertedQueryable;
            if ((null != innerQueryable) && (innerQueryable != this) && (innerQueryable.Expression is ConstantExpression))
            {
                return innerQueryable.ConvertExpression(innerQueryable.Expression);
            }
        }
        if (null != dummyQueryableValueConstant)
        {
            return this.ConvertExpression(dummyQueryableValueConstant.StoredQueryable.Expression);
        }
    }
    return expandedExpression;
}

我们已经重写了IQueryable Provider方法,以便在执行前调用我们的转换:

public override object Execute(Expression expression)
{
    var constructors = AddConstructorsFromExpression(expression);
    var convertedExpression = this.ExpressionConverter.Visit(expression);
    var result = this._queryProvider.Execute(convertedExpression);
    if (null == result)
    {
        return null;
    }
    var types = GetInnerAndOuterTypesForInnerObject(result, convertedExpression.Type, expression.Type);

    return this._innerToOuterConverterFactory()
                   .Convert(result, types.Key, types.Value, x => GetConstructorOrNull(constructors, x));
}

当我不使用GroupBy或Select(x => new {x})时,Include语句正常工作;我的第一个直觉是可查询生成的表达式是错误的。所以我基于使用我们的上下文和使用northwind上的entityframework来映射表达式

  

.Call System.Linq.Queryable.GroupBy(       .Call System.Linq.Queryable.Where(           .Call(.Call .Constant1 [StagingNorthWindTest.Customer]>(System.Data.Entity.Core.Objects.ObjectQuery1 [StagingNorthWindTest.Customer])。MergeAs(.Constant(AppendOnly))           ).IncludeSpan(.Constant(System.Data.Entity.Core.Objects.Span)),           '(。Lambda#Lambda1))

     

.Lambda#Lambda1(StagingNorthWindTest.Customer $ x){       真正   }

     

.Lambda#Lambda2(StagingNorthWindTest.Customer $ x){       $ x.City   }

  

.Call System.Linq.Queryable.GroupBy(       .Call System.Linq.Queryable.Where(           .Call(.Call .Constant1 [BDBPayroll.Services.DataAccess.RowEntities.DivisionRptPackageRow]>(System.Data.Entity.Core.Objects.ObjectQuery1 [BDBPayroll.Services.DataAccess.RowEntities.DivisionRptPackageRow])。MergeAs(.Constant( AppendOnly))           ).IncludeSpan(.Constant(System.Data.Entity.Core.Objects.Span)),           '(。Lambda#Lambda1))

     

.Lambda#Lambda1(BDBPayroll.Services.DataAccess.RowEntities.DivisionRptPackageRow $ x)   {       真正   }

     

.Lambda#Lambda2(BDBPayroll.Services.DataAccess.RowEntities.DivisionRptPackageRow $ x)   {       $ x.DivisionRptPackageID   }

对于针对northwind的相同操作生成的表达式与我们的上下文使用相同的语法和路径。然而,内部DbQueryProvider似乎忽略了我的包含跨度,尽管它们正确包含包含。

实体框架在生成Projections I.E Group by或匿名选择时是否有什么特别之处?

修改

当我使用普通的EF时,我终于找到了一个小的区别,include调用了dbQuery Path,而当我使用我的上下文时,它调用了QueryableExtensions.CommonInclude

  if (dbQuery != null)
    return (IQueryable<T>) dbQuery.Include(path);
  ObjectQuery<T> objectQuery = source as ObjectQuery<T>;
  if (objectQuery != null)
    return (IQueryable<T>) objectQuery.Include(path);
  return QueryableExtensions.CommonInclude<IQueryable<T>>(source, path);

这两种方法有什么区别?

0 个答案:

没有答案