C# 如何从IQueryable获取原始收藏<;T>;
考虑以下几点:C# 如何从IQueryable获取原始收藏<;T>;,c#,linq,iqueryable,C#,Linq,Iqueryable,考虑以下几点: T[] itemArray = // initialized values IQueryable<T> itemQuery = itemArray.AsQueryable().Where(*/some query*/).Skip(5).Etc() ... T[]itemArray=//初始化值 IQueryable itemQuery=itemArray.AsQueryable()。其中(*/some query*/)。跳过(5).Etc()。。。 是否可以从it
T[] itemArray = // initialized values
IQueryable<T> itemQuery = itemArray.AsQueryable().Where(*/some query*/).Skip(5).Etc() ...
T[]itemArray=//初始化值
IQueryable itemQuery=itemArray.AsQueryable()。其中(*/some query*/)。跳过(5).Etc()。。。
是否可以从itemQuery
获取基础集合或数据集(在本例中为itemrarray
)?在我看来,如果在计算查询表达式时,必须对原始集合进行计算,因此该集合必须存储在IQueryable中或由IQueryable引用
如何做到这一点
注:这是使用MongoDB linq驱动程序(来自10gen)的一个更大项目的一部分,我们试图从基于mongo集合的IQueryable中提取原始MongoCollection。尽管我们专门针对MongoDB使用IQueryable,但这个问题的答案应该是IQueryable固有的,因此独立于MongoDB驱动程序。IQueryable最有可能引用底层集合(可能通过若干层间接寻址),但是它不会公开暴露,所以你将无法访问它,至少在任何我认为合理的,而不是一个非常非常凌乱的黑客的情况下。 < P>不,每个查询都独立执行,剩下的就是查询本身的结果集。内存对象中没有包含原始集合的内容,也没有对原始集合的任何可访问引用。考虑到原始集合现在可能为null或超出范围,这将是危险的。如果您需要删除原始集合,则需要将其保留在范围内,直到您完全完成为止。这是一种欺骗,但在您的上下文中可能有意义:
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
}
当您需要源代码序列时,您可以通过source
成员访问它,也可以通过as
cast访问它
var s = itemQuery.Source;
+1-我相信EF Linq提供程序只存储任何过滤器等,以便投影SQL,因此可能无法使用
IQueryable
引用访问整个表。我希望MongoDB提供程序与之类似,不会过滤内存中的数据。好吧,原始集合必须存在于某个地方。这里的查询使用的是延迟执行,所以它只是定义如何从集合中提取数据,直到您尝试枚举它,它才真正提取数据。因此,它需要有一个对实际收藏的引用(至少是间接引用)。@Servy:Yah,我用“可访问”这个词进行了编辑。出于执行目的,存在对原始集合的引用,但没有可访问的引用。我不是100%确定,但我相信一旦执行完毕,这个引用就会被丢弃。不过,不要引用我的话。在我看来,我在某个地方读到了这样的东西(或者至少是让我相信的东西:),虽然定制查询提供者确实可以做到这一点,但明智的人是不会做到的。对于初学者来说,您可以多次枚举[大多数]查询,因此故意丢弃枚举“您自己”所需的信息会阻止这一点(标准提供者都不会这样做)。正如我在回答中所说,您可能(实际上)无法从IQueryable
中获取引用,但它就在那里(某个地方)。@Servy:一旦执行发生,新数据将加载到单独的内存空间中。原始引用只需要存在足够长的时间就可以执行。虽然现在你激起了我的好奇心。我将不得不运行一些范围测试,以查看当源集合在执行之后和之前超出范围时,延迟执行会发生什么情况。正如我所说,查询将在源集合的整个生命周期中保留对源集合的引用,因此,根据定义,在查询发生之前,源集合不能超出范围。引用实际集合(实际程序员有权访问)的某些变量可能超出范围,但在可查询项消失之前,基础集合(本例中为数组)不能超出范围。如果它这样做了(可能是通过表示不安全的代码),那么查询将中断,因为它将查询不再存在的数据。
var s = itemQuery.Source;