Как создать метод расширения Prepend для IQueryable <T>, который совместим с Linq для Entities 4.0? - PullRequest
0 голосов
/ 10 декабря 2010

Для проекта, использующего 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.Business.Pocos.ExclusionIncomeType'. В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid ')."

Я пытался найти похожие понятия, включая добавление значения, но безрезультатно.

Идеи

Ответы [ 3 ]

1 голос
/ 10 декабря 2010

Вы можете использовать итератор для создания нового 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;
    }
}

Это создаст перечислитель, который сначала вернет элемент по умолчанию, а затем перечислит запрос.

0 голосов
/ 05 мая 2011
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 голосов
/ 18 декабря 2010

Окончательный ответ:

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