简体   繁体   English

非通用AsEnumerable

[英]Non-Generic AsEnumerable

How would you suggest using AsEnumerable on a non-generic IQueryable ? 您如何建议在非通用IQueryable上使用AsEnumerable

I cannot use the Cast<T> or OfType<T> methods to get an IQueryable<object> before calling AsEnumerable , since these methods have their own explicit translation by the underlying IQueryProvider and will break the query translation if I use them with a non-mapped entity (obviously object is not mapped). 在调用AsEnumerable之前,我无法使用Cast<T>OfType<T>方法获取IQueryable<object> ,因为这些方法由底层IQueryProvider有自己的显式转换,如果我将它们与非一起使用,它将破坏查询转换映射实体(显然对象未映射)。

Right now, I have my own extension method for this (below), but I'm wondering if there's a way built into the framework. 现在,我有自己的扩展方法(下图),但我想知道是否有一种内置于框架中的方法。

public static IEnumerable AsEnumerable(this IQueryable queryable)
{
    foreach (var item in queryable)
    {
        yield return item;
    }
}

So, with the above extension method, I can now do: 那么,通过上面的扩展方法,我现在可以做到:

IQueryable myQuery = // some query...

// this uses the built in AsEnumerable, but breaks the IQueryable's provider because object is not mapped to the underlying datasource (and cannot be)
var result = myQuery.Cast<object>().AsEnumerable().Select(x => ....);

// this works (and uses the extension method defined above), but I'm wondering if there's a way in the framework to accomplish this
var result = myQuery.AsEnumerable().Cast<object>().Select(x => ...);

JaredPar's answer in other words: 换句话说JaredPar的答案是:

public static IEnumerable AsEnumerable(this IEnumerable source)
{
    return source;
}

Usage: 用法:

IQueryable queryable = // ...
IEnumerable enumerable = queryable.AsEnumerable();
IEnumerable<Foo> result = enumerable.Cast<Foo>();
//                                     ↑
//                           Enumerable.Cast<TResult>(this IEnumerable source)

Since the interface IQueryable inherits from IEnumerable why not: 由于接口IQueryable继承自IEnumerable为什么不:

IQueryable queryable;
IEnumerable<T> = (queryable as IEnumerable).Cast<T>();

Edit 编辑
There are two Cast<> extension methods: 有两种Cast<>扩展方法:

public static IQueryable<TResult> Cast<TResult>(this IQueryable source)
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)

Which one is called is statically decided by the compiler. 调用哪一个是由编译器静态决定的。 So casting an IQueryable as an IEnumerable will cause the second extension method to be called, where it will be treated as an IEnumerable . 因此,将IQueryable作为IEnumerable将导致调用第二个扩展方法,其中它将被视为IEnumerable

The type IQueryable inherits from the non-generic IEnumerable so this extension method doesn't seem to serve any purpose. IQueryable类型继承自非泛型IEnumerable因此这种扩展方法似乎没有任何用途。 Why not just use it as IEnumerable directly? 为什么不直接将它用作IEnumerable

To clarify, you are trying to add a "force expression evaluation" to your linq expression tree so that part of the expression tree is evaluated against the underlying provider (linq to SQL for example) and the rest is evaluated in memory (linq to objects). 为了澄清,您正在尝试向linq表达式树添加“强制表达式求值”,以便针对底层提供程序(例如linq to SQL)计算表达式树的一部分,并在内存中评估其余部分(linq到对象) )。 But you want to be able to specify the entire express tree without actually executing the query or reading any results into memory. 但是您希望能够在不实际执行查询或将任何结果读入内存的情况下指定整个快速树。

This is a good thing and it shows some insight into the way that Linq works. 这是一件好事,它显示了对Linq工作方式的一些了解。 Good job. 做得好。

The confusion I see here is your use of "AsEnumerable" as the method name. 我在这里看到的困惑是你使用“AsEnumerable”作为方法名称。 To me (and I think many people who thinq linq ) "AsEnumerable" is too similar to the "AsQueryable" method which is essentially a cast, not an actual evaluator. 对我来说(我认为很多人瘦身linq)“AsEnumerable”太过类似于“AsQueryable”方法,它本质上是一个演员,而不是一个实际的评估者。 I propose you rename your method to "Evaluate". 我建议你将你的方法重命名为“Evaluate”。 This is my Evaluate() method from my personal Linq extensions library. 这是我个人Linq扩展库中的Evaluate()方法。

    /// <summary>
    /// This call forces immediate evaluation of the expression tree. 
    /// Any earlier expressions are evaluated immediately against the underlying IQueryable (perhaps
    /// a Linq to SQL provider) while any later expressions are evaluated against the resulting object
    /// graph in memory.
    /// This is one way to determine whether expressions get evaluated by the underlying provider or
    /// by Linq to Objects in memory.
    /// </summary>
    public static IEnumerable<T> Evaluate<T>(this IEnumerable<T> expression)
    {
        foreach (var item in expression)
        {
            yield return item;
        }
    }

    /// <summary>
    /// This call forces immediate evaluation of the expression tree. 
    /// Any earlier expressions are evaluated immediately against the underlying IQueryable (perhaps
    /// a Linq to SQL provider) while any later expressions are evaluated against the resulting object
    /// graph in memory.
    /// This is one way to determine whether expressions get evaluated by the underlying provider or
    /// by Linq to Objects in memory.
    /// </summary>
    public static IEnumerable Evaluate(this IEnumerable expression)
    {
        foreach (var item in expression)
        {
            yield return item;
        }
    }

This allows you to write a query where some of the query is evaluated by SQL (for example) and the rest is evaluated in memory. 这允许您编写一个查询,其中一些查询由SQL评估(例如),其余查询在内存中计算。 A good thing. 好事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM