如何从IQueryable <t> </t>获取原始集合

时间:2012-10-03 19:53:44

标签: c# linq iqueryable

请考虑以下事项:

T[] itemArray = // initialized values
IQueryable<T> itemQuery = itemArray.AsQueryable().Where(*/some query*/).Skip(5).Etc() ...

是否可以从itemArray获取基础集合或数据集(在本例中为itemQuery)?在我看来,如果在评估查询表达式时,必须针对原始集合对其进行评估,因此该集合必须存储在IQueryable中或由IQueryable引用。

如何做到这一点?

注意:
这是一个包含MongoDB linq驱动程序(来自10gen)的大型项目的一部分,我们正在尝试从基于mongo集合的IQueryable中提取原始MongoCollection。虽然我们使用的是IQueryable&lt;&gt;特别是对于MongoDB,这个问题的答案应该是IQueryable&lt;&gt;所固有的。因此独立于MongoDB驱动程序。

3 个答案:

答案 0 :(得分:3)

IQueryable很可能确实有对底层集合的引用(可能通过多个间接层),但它不会公开暴露,因此您将无法访问它,至少不会以任何方式考虑合理而不是非常非常混乱的黑客。

答案 1 :(得分:0)

不,每个查询都是独立执行的,而您剩下的只是查询本身的结果集。内存对象中没有任何内容包含原始集合,也没有任何对原始集合的可访问引用。考虑到原始集合现在可能为空或超出范围,这甚至是允许的。如果您需要原始集合,则需要将其保留在范围内,直到完成它为止。

答案 2 :(得分:0)

这是作弊,但也许在你的背景下有意义:

interface IReferencedQueryable<T> : IQueryable<T>
{
    IEnumerable<T> Source { get; }
}

static class IReferencedQueryableExtensions
{
    public static IReferencedQueryable<T> AsReferencedQueryable<T>(
        this IEnumerable<T> source)
    {
        return ReferencedQueryable.From(source);
    }

    class ReferencedQueryable<T> : IReferencedQueryable<T>
    {
        public IEnumerable<T> Source { get; private set; }

        ReferencedQueryable(IEnumerable<T> source)
        {
            Source = source;
        }

        static IReferencedQueryable<T> From(IEnumerable<T> source)
        {
            return new ReferencedQueryable(source);
        }

        // all the IQueryable members would be 
        // implemented through AsQueryable()
        // ...
    }

    public static IReferencedQueryable<T> Where<T>(
        this IReferencedQueryable<T> source, 
        Expression<Func<T, bool>> predicate)
    {
        return ReferencedQueryable.From(
            ((IQueryable<T>)source).Where(predicate));
    }

    // do the same for all the Linq extension methos you want to support
}

您可以这样使用它:

T[] itemArray = // initialized values
var itemQuery = itemArray.AsReferencedQueryable()
                         .Where(*/some query*/)
                         .Skip(5)
                         .Etc() ...

当您需要源序列时,可以通过Source成员访问它,可能通过as强制转换。

var s = itemQuery.Source;