关于c#:从IQueryable< T>?中提取Linq查询

Extract the Linq query from an IQueryable<T>?

我继承了一个应用程序,并试图调试在我之前编写的实体框架6中运行的一个查询的结果中缺少字段的原因。

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

理想情况下,我希望看到"从xtable.include中选择x"("someothertable")。在哪里(谓词)"拼凑在一起?我知道如何查看生成的SQL,但这对确定需要更改的参数没有多大帮助。

功能如下。在应用skip/take/toarray/tolist之前,我基本上需要在两个返回语句之一中使用end linq语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    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();
        }
    }


据我所见,确实没有太多的提取工作要做,因为很多提取工作正在被传递。

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

正在给您传递的T类型的整个dbset。(我建议对其使用where T : DbSet类型约束,不确定这是否是确切的语法,但请确保只能传递entityContext知道的类型(第一个参数)。

1
2
3
4
if (filter != null)
        {
            query = query.Where(filter);
        }

此代码中没有"where"子句,它正通过System.Linq.Expressions.Expression> filter参数传递给函数。

1
2
3
4
5
6
7
8
if (!string.IsNullOrEmpty(includeProperties))
        {
            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }
        }

此代码中也没有"include"子句,它正在传递给函数。

下一个大模块是处理"orderby"的东西,并返回IEnumerableSkip(skip).Take(take).ToArray().ToList();固定在末端。

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

例如:

1
2
3
4
5
6
7
8
9
GetPagedEntity<User>(
entityContext:declaredContext,
skip:20,
take:40,
filter: (u => u.IsActive == true),
orderBy:"FirstName,LastName",
includeProperties:"table1,table2",
out count:declaredInt
)

看起来像这样:

1
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方法采用指定数量之前的计数。希望这有帮助,对不起,如果我的语法有点不正确。


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

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

enter image description here