繁体   English   中英

非通用AsEnumerable

[英]Non-Generic AsEnumerable

您如何建议在非通用IQueryable上使用AsEnumerable

在调用AsEnumerable之前,我无法使用Cast<T>OfType<T>方法获取IQueryable<object> ,因为这些方法由底层IQueryProvider有自己的显式转换,如果我将它们与非一起使用,它将破坏查询转换映射实体(显然对象未映射)。

现在,我有自己的扩展方法(下图),但我想知道是否有一种内置于框架中的方法。

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

那么,通过上面的扩展方法,我现在可以做到:

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的答案是:

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

用法:

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

由于接口IQueryable继承自IEnumerable为什么不:

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

编辑
有两种Cast<>扩展方法:

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

调用哪一个是由编译器静态决定的。 因此,将IQueryable作为IEnumerable将导致调用第二个扩展方法,其中它将被视为IEnumerable

IQueryable类型继承自非泛型IEnumerable因此这种扩展方法似乎没有任何用途。 为什么不直接将它用作IEnumerable

为了澄清,您正在尝试向linq表达式树添加“强制表达式求值”,以便针对底层提供程序(例如linq to SQL)计算表达式树的一部分,并在内存中评估其余部分(linq到对象) )。 但是您希望能够在不实际执行查询或将任何结果读入内存的情况下指定整个快速树。

这是一件好事,它显示了对Linq工作方式的一些了解。 做得好。

我在这里看到的困惑是你使用“AsEnumerable”作为方法名称。 对我来说(我认为很多人瘦身linq)“AsEnumerable”太过类似于“AsQueryable”方法,它本质上是一个演员,而不是一个实际的评估者。 我建议你将你的方法重命名为“Evaluate”。 这是我个人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;
        }
    }

这允许您编写一个查询,其中一些查询由SQL评估(例如),其余查询在内存中计算。 好事。

暂无
暂无

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

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