开发者

How to create Prepend extension method for IQueryable<T> which is compatible with Linq to Entities 4.0?

For a project using LINQ to Entities 4.0, I have a setting in which I need to return a query with a (constant) value prepended. If I were coding it in SQL it would look something like this:

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

For this project, I would like to create a generic extension method to IQueryable that accepts a constant value returns a query with the constant value prepended as its result. The process should not trigger enumeration as I don't want the query to trigger a database hit unless the other code in the application actually enumerates against the query.

Ideally, I would like the IQueryable result to be joinable to other Linq to Entities queries a开发者_运维问答nd processable by the L2E provider.

I have tried a couple of varations, but realized they were going to trigger enumeration instead of adding to the query. My latest attempt extends the query without enumerating (as desired), but returns an error:

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

The error is, "Unable to create a constant value of type 'OCEAN.Business.Pocos.ExclusionIncomeType'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.".

I've tried searching for similar concepts, including appending a value, but to no avail.

Ideas?


You can use an iterator to create a new IEnumerable<T> instance that returns your default value first:

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

This will create an enumerator that will first return your default item, and then enumerate through the query.


Final answer:

    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();
    }


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(); 
} 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜