如何在需要计数和项目时避免编写重复查询

How to avoid writing duplicate queries when needing counts and then items

我构建了一个连接大约六个表的 LINQ 查询。问题是,出于分页目的,我想首先计算将返回多少项目。因此,我 运行 遇到的问题是必须编写两次完全相同的查询:一次获取项目计数,另一次构建我的项目集合。

示例:

using (var context = new DbContext())
{
    var items = from i in context.Table1
                join a in context.TableA on i.SomeProperty equals a.SomeProperty
                join b in context.TableB on i.SomeOtherProperty equals b.SomeProperty
                join c in context.TableC on i.AnotherProperty equals c.SomeProperty
                etc.
                etc.
                select i;

    count = items.Count();
}   

return count;

.
.
.

using (var context = new DbContext())
{
    var items = from i in context.Table1
                join a in context.TableA on i.SomeProperty equals a.SomeProperty
                join b in context.TableB on i.SomeOtherProperty equals b.SomeProperty
                join c in context.TableC on i.AnotherProperty equals c.SomeProperty
                etc.
                etc.
                select new
                {
                    DynamicProp1 = i.SomeProperty,
                    DyanmicProp2 = a.SomeProperty,
                    DyanmicProp3 = b.SomePropery,
                    etc.
                    etc.
                }
    ... do some stuff with 'items'...
}      

我想不出任何方法来避免这种重复查询。我需要访问所有连接的表才能构建我的集合。如果有任何提示或建议,我将不胜感激。

您可以创建方法来获取上下文和 return 具有所有需要实体的项目的 IQueryable:

class Holder
{
  TableAItem A{get;set;}
  TableBItem B{get;set;}
  ...
}

IQueryable<Holder> GetQuery(DbContext context)
{
  return from i in context.Table1
         join a in context.TableA on i.SomeProperty equals a.SomeProperty
         join b in context.TableB on i.SomeOtherProperty equals b.SomeProperty
         join c in context.TableC on i.AnotherProperty equals c.SomeProperty
         ...
         select new Holder
         {
           A = i,
           B = b
           ....
         };
}

using (var context = new DbContext())
{
    var items = GetQuery(context);

    count = items.Count();
}   

return count;


using (var context = new DbContext())
{
    var items = from r in GetQuery(context)
                select new
                {
                    DynamicProp1 = r.a.SomeProperty,
                    DyanmicProp2 = r.a.SomeProperty,
                    DyanmicProp3 = r.b.SomePropery,
                    etc.
                    etc.
                }
    ... do some stuff with 'items'...
} 

请记住,进行查询不会执行查询,这称为延迟执行。那么为什么不进行查询,然后将其作为 IQueryable<> 对象传递。例如,考虑以下代码:

只是 return 字符串最后一个字符的简单方法,但它也会写出它在做什么:

public char GetLastChar(string input)
{
    Console.WriteLine("GetLastChar from {0}", input);
    return input.Last();
}

现在这段代码使用的方法是:

var listOfStuff = new List<string> { "string1", "string2", "string3" };

Console.WriteLine("Making the query");

var results = from s in listOfStuff
              select GetLastChar(s);

Console.WriteLine("Before getting count");
var count = results.Count();
Console.WriteLine("Now enumerating the query");

foreach(var s in results)
{
    Console.WriteLine(s);
}

您将看到如下输出:

Making the query
Before getting count
GetLastChar from string1
GetLastChar from string2
GetLastChar from string3
3
Now enumerating the query
GetLastChar from string1
1
GetLastChar from string2
2
GetLastChar from string3
3