如何为与Linq to Entities 4.0兼容的IQueryable <t>创建Prepend扩展方法?</t>

时间:2010-12-10 16:20:04

标签: entity-framework .net-4.0 linq-to-entities iqueryable

对于使用LINQ to Entities 4.0的项目,我有一个设置,我需要返回一个前缀为(常量)值的查询。如果我在SQL中编写它,它看起来像这样:

select 0 as ID, 'default' as Name
union
select ID, Name from X

对于这个项目,我想为IQueryable创建一个通用的扩展方法,它接受一个常量值,返回一个前缀为常量值的查询作为结果。该进程不应该触发枚举,因为我不希望查询触发数据库命中,除非应用程序中的其他代码实际枚举查询。

理想情况下,我希望IQueryable结果可以连接到其他Linq to Entities查询并由L2E提供程序处理。

我尝试了几个版本,但意识到它们会触发枚举而不是添加到查询中。我的最新尝试扩展了查询而没有枚举(根据需要),但返回错误:

    public static IQueryable<T> Prepend<T>(
        this IQueryable<T> query
        , T value
        )
    {
        return query
            .Where(t => false).DefaultIfEmpty(value)
            .Concat(query);
    }

错误是“无法创建类型为'OCEAN.B​​usiness.Pocos.ExclusionIncomeType'的常量值。在此上下文中仅支持基本类型(例如Int32,String和Guid')。”。< / p>

我尝试过搜索类似的概念,包括附加值,但无济于事。

想法?

3 个答案:

答案 0 :(得分:1)

您可以使用iterator创建一个新的IEnumerable<T>实例,该实例首先返回您的默认值:

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> sequence, T value) 
{
    yield return value;
    foreach (var item in sequence)
    {
        yield return item;
    }
}

这将创建一个枚举器,它将首先返回您的默认项,然后枚举查询。

答案 1 :(得分:0)

最终答案:

    private static IEnumerable<T> PrependEnumerator<T>(this IEnumerable<T> sequence, T value)  
    { 
        yield return value; 
        foreach (var item in sequence) 
        { 
            yield return item; 
        } 
    } 

    public static IQueryable<T> Prepend<T>(
        this IQueryable<T> query
        , T value
        )
    {
        return query.PrependEnumerator(value).AsQueryable();
    }

答案 2 :(得分:0)

private static IEnumerable<T> PrependEnumerator<T>(
    this IEnumerable<T> sequence, 
    T value
    ) 
{ 
    yield return value; 
    foreach (var item in sequence) { yield return item; } 
} 
public static IQueryable<T> Prepend<T>( 
    this IQueryable<T> query , 
    T value 
    ) 
{ 
    return query.PrependEnumerator(value).AsQueryable(); 
}