获取 IQueryable的计数

发布于 2024-10-17 08:23:09 字数 417 浏览 2 评论 0原文

假设我们有以下集合

 IEnumerable<int> list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
 var query = list.Skip(5).Take(4);
 SomeMethod(query.AsQueryable()); 
 .
 .
 .
 public void SomeMethod(IQueryable<T> query)
 {
      var collectionCount = ?????  // count should be 10 not 4.
      ...
 }

如何获取 SomeMethod 中查询的原始集合的计数(不应用 Skip 和 Take 子查询)。

谢谢。

Assume we have the following collection

 IEnumerable<int> list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
 var query = list.Skip(5).Take(4);
 SomeMethod(query.AsQueryable()); 
 .
 .
 .
 public void SomeMethod(IQueryable<T> query)
 {
      var collectionCount = ?????  // count should be 10 not 4.
      ...
 }

How can I get the count of the original collection (without applying Skip and Take sub-queries) of the query in the SomeMethod.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌化 2024-10-24 08:23:09

您无法获取这些信息(除非做一些硬核反射的事情)。它根本不存在了。就像您想从类似这样的内容中提取原始计数:

var list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
SomeMethod(list[3]);

public void SomeMethod(int number)
{
  var collectionCount = ?????  // count should be 10
  ...
}

我认为您可能能够获取信息,如果您不传递IQueryable,而是传递Expression 然而,即使是这个案子也不会简单。

每条评论添加

这并不像你想象的那么简单;我什至不认为这完全可能。但是,对于某些有限的用例,它可能有效。我很快就破解了一种方法,该方法可以“删除”应用于查询的任何 Skip a Take 并返回原始计数。尝试一下,YMMV:

public int CountOriginal<T>(IQueryable<T> query)
{
    var ex = query.Expression;
    while (ex.NodeType == ExpressionType.Call)
    {
        var call = (MethodCallExpression)ex;

        if (call.Method.Name != "Skip" && call.Method.Name != "Take") break;

        ex = call.Arguments[0];
    }
    var enumerable = Expression.Lambda(ex).Compile().DynamicInvoke(null) as IEnumerable<T>;
    if (enumerable == null) throw new NotImplementedException();
    return enumerable.Count();
}

There is no way you could get the information (except maybe by doing some hardcore reflection stuff). It is simply not there anymore. It’s like you wanted to extract the original count from something like this:

var list = new List<int> { 11, 12, 13, 14, 15, 16, 17, 18, 19, 10 };
SomeMethod(list[3]);

public void SomeMethod(int number)
{
  var collectionCount = ?????  // count should be 10
  ...
}

I think you might be able to get the information if instead of IQueryable, you would pass Expression, however, even this case would not be simple.

Added per comments:

It is not as simple as you might think; I don’t even think it is possible fully generally. However, for some limited use cases it might work. I have quickly hacked a method which “removes” any Skip a Take applied to the query and returns the original count. Give it a try, YMMV:

public int CountOriginal<T>(IQueryable<T> query)
{
    var ex = query.Expression;
    while (ex.NodeType == ExpressionType.Call)
    {
        var call = (MethodCallExpression)ex;

        if (call.Method.Name != "Skip" && call.Method.Name != "Take") break;

        ex = call.Arguments[0];
    }
    var enumerable = Expression.Lambda(ex).Compile().DynamicInvoke(null) as IEnumerable<T>;
    if (enumerable == null) throw new NotImplementedException();
    return enumerable.Count();
}
夜未央樱花落 2024-10-24 08:23:09

list.Count 应返回原始列表的计数

list.Count should return the count of the original list

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文