【问题标题】:Extract the Linq query from an IQueryable<T>?从 IQueryable<T> 中提取 Linq 查询?
【发布时间】:2015-04-24 02:29:50
【问题描述】:

我继承了一个应用程序,并正在尝试调试为什么在我之前编写的通过 Entity Framework 6 运行的查询之一的结果中缺少字段。

最初的开发人员创建了一个系统,该系统接受实体上下文、过滤器 Lambda 表达式、按限制排序和包含的属性。为了让我使用查询来查看缺少的内容,我想从函数末尾放在一起的 IQueryable 中提取 Linq/Lambda 查询,以便在 Linqpad 中执行它。

理想情况下,我想看看什么样的“select x from XTable.Include("SomeOtherTable").Where(Predicates)" 拼凑在一起?我知道如何查看生成的 SQL,但这对找出需要更改的参数没有多大帮助。

这是函数。在应用 Skip/Take/ToArray/ToList 之前,我基本上需要两个 return 语句之一中的 end linq 语句。

    protected override IEnumerable<T> GetPagedEntity(MyDBContext entityContext, int skip, int take, System.Linq.Expressions.Expression<Func<T, bool>> filter, string orderBy, string includeProperties, out int count)
    {
        IQueryable<T> query = entityContext.Set<T>();
        string[] orderby = !string.IsNullOrEmpty(orderBy) ? orderBy.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) : null;
        if (filter != null)
        {
            query = query.Where(filter);
        }
        count = query.Count();
        if (!string.IsNullOrEmpty(includeProperties))
        {
            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }
        }
        if (!string.IsNullOrWhiteSpace(orderBy) && orderby != null && orderby.Length > 0)
        {
            for (int i = 0; i < orderby.Length; i++)
            {
                if (i == 0)
                {
                    if (orderby[i].ToLower().Contains(" desc"))
                    {
                        query = FilterExpressionUtil.OrderByDescending(query, orderby[i].Trim().Split(' ')[0]);
                    }
                    else
                    {
                        query = FilterExpressionUtil.OrderBy(query, orderby[i].Trim());
                    }
                }
                else
                {
                    if (orderby[i].ToLower().Contains(" desc"))
                    {
                        query = FilterExpressionUtil.ThenByDescending(query as IOrderedQueryable<T>, orderby[i].Trim().Split(' ')[0]);
                    }
                    else
                    {
                        query = FilterExpressionUtil.ThenBy(query as IOrderedQueryable<T>, orderby[i].Trim());
                    }
                }
            }
            return query.Skip(skip).Take(take).ToArray().ToList();
        }
        else
        {
            return query.OrderBy(a => 1).Skip(skip).Take(take).ToArray().ToList();
        }
    }

【问题讨论】:

  • 如果可能的话,尝试完全摆脱这个方法,因为除了完全模糊之外,它会导致执行2次查询,通过在这个方法中执行query.Count(),在返回查询之前.
  • 感谢您的意见。如果我有我的选择,我会把这该死的东西都吃掉,但现在我必须克服我的限制和我的最后期限。
  • 我猜你应该在使用 ToArray() 运行它之前检查查询对象的 Expression 属性。

标签: c# linq entity-framework lambda


【解决方案1】:

据我所见,实际上没有太多提取工作要做,因为其中很多都被传入了。

IQueryable<T> query = entityContext.Set<T>();

正在为您提供您传入的 T 类型的整个 DBSet。(我建议在其上放置 where T : DbSet 类型约束,不确定这是否是确切的语法,但请确保您只能传入一个entityContext(第一个参数)知道的类型。

if (filter != null)
        {
            query = query.Where(filter);
        }

此代码中没有“Where”子句,它通过System.Linq.Expressions.Expression&lt;Func&lt;T, bool&gt;&gt; filter 参数传递给函数。

if (!string.IsNullOrEmpty(includeProperties))
        {
            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }
        }

此代码中也没有“包含”子句,它被传递到函数中。

下一个大块正在处理“OrderBy”内容,并返回IEnumerable&lt;T&gt;,并在末尾添加Skip(skip).Take(take).ToArray().ToList();


每次调用此函数时,您的问题的答案都会有所不同。


例如:

GetPagedEntity<User>(
entityContext:declaredContext, 
skip:20, 
take:40, 
filter: (u => u.IsActive == true), 
orderBy: "FirstName,LastName", 
includeProperties: "table1,table2", 
out count:declaredInt
)

看起来像这样:

declaredContext.Set<User>().Where(u => u.IsActive == true).Include("table1").Include("table2").OrderBy(u => u.FirstName).ThenBy(u => u.LastName).Skip(20).Take(40).ToArray().ToList();

输出参数count 将在Take 方法获取指定数量之前返回计数。希望这会有所帮助,如果我的语法有点不对,请见谅。

【讨论】:

  • 谢谢。我可能只是需要另一双眼睛来帮我看。
【解决方案2】:

您所要做的就是放置一个断点并在查询变量上执行快速监视。也可以linq查询。

下面的示例显示了生成的 LINQ 查询。

【讨论】:

  • 当我尝试在值中看到的只是 {System.Data.Entity.Infrastructure.DbQuery}
猜你喜欢
  • 2020-12-22
  • 2011-02-15
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多