Использование делегата CompiledQuery в объединении? - PullRequest
5 голосов
/ 01 сентября 2011

У меня есть вопрос, связанный с моим предыдущим вопросом . В существующем бите LINQ, который включает несколько объединений , я пытаюсь взять каждый отдельный метод, включающий объединение, и преобразовать его в CompiledQuery .

Во-первых, обычный метод LINQ:

private IQueryable<Widget> GetWidgetQuery()
{
    return db.Widgets.Where(u => (!u.SomeField.HasValue || !u.SomeField.Value));
}

И здесь определение делегата (поля) для CompiledQuery по этим строкам:

private static readonly Func<DBDataContext, IQueryable<Widget>> GetWidgetQuery = 
    CompiledQuery.Compile((DBDataContext db) => 
    db.Widgets.Where(u => (!u.SomeField.HasValue || !u.SomeField.Value)));

Если навести указатель мыши на обычный оператор LINQ для метода GetWidgetQuery () , я увижу, что это метод , как показано ниже:

(method) IQueryable<Widget> GetWidgetQuery()

Однако делегат скомпилированного запроса ( поле ) отличается следующим образом:

(field) Func<DBDataContext, IQueryable<Widget>> GetWidgetQuery

После выполнения последнего как части оператора LINQ синтаксис отличается следующим образом. Во-первых, обычное участие LINQ в объединении:

var myquery =
    from wxr in GetWidgetXRQuery()
    join w in GetWidgetQuery() on wxr.WidgetID equals w.ID
    select new DTO.WidgetList
    {
        ...
    }

И вот, вызов CompiledQuery в виде делегата:

var myquery =
    from wxr in GetWidgetXRQuery()
    join w in GetWidgetQuery.Invoke(myContext) on wxr.WidgetID equals w.ID
    select new DTO.WidgetList
    {
        ...
    }

Первый возвращает ожидаемый набор результатов; последнее, когда я пытаюсь myquery.ToList () , выдает stackoverflow исключение, отчасти связанное с этим ограничением .NET 3.5 , я думаю.

Может кто-нибудь помочь мне понять, как скомпилированный оператор, существующий как поле (или, я думаю, я должен сказать делегат), а не метод, убивает мой запрос? Короче говоря, я знаю, что я делаю неправильно, но я не уверен, что понимаю, что я неправильно понимаю.

Ответы [ 2 ]

1 голос
/ 01 сентября 2011

Я попытался сделать примерно то же самое, что вы делаете на EF 4, и все, кажется, работает нормально. Так что это либо проблема EF 3.5, либо она связана с вашей реализацией GetWidgetXRQuery, либо с какой-то их комбинацией.

Но реальная мысль, которую я хотел бы сделать, заключается в том, что, как Рой Гуд заявил в ответе на свой предыдущий вопрос, вы теряете все преимущества предварительно скомпилированного запроса, как только вы расширяете этот запрос в любом путь. Пытаясь выполнить присоединение к вашему запросу, вы преобразуете его в простой старый запрос. Так что вы можете просто использовать не скомпилированную версию, которая работает для вас.

Обновление

Понял, что вы говорили о LINQ to SQL. Этот вид запроса, по-видимому, имеет поддержку в Entity Framework, но не LINQ to SQL. В .NET 4 я получаю следующую ошибку:

IQueryable, который возвращает выражение константы с собственной ссылкой, не поддерживается.

Это не так много значит для меня, но я предполагаю, что это как-то связано с тем, как скомпилированный запрос представляется внутренне. Я все еще получаю ту же ошибку, если оцениваю запрос в переменную и позже использую эту переменную в запросе, так что это явно не имеет никакого отношения к разнице между делегатом и функцией. Я по-прежнему утверждаю, что скомпилированный запрос не подходит для использования здесь. Либо вам нужно создать один большой скомпилированный запрос для представления всего запроса, который вы хотите выполнить, либо использовать обычные запросы, если вы хотите соединить их таким образом.

0 голосов
/ 05 декабря 2018

Я только что столкнулся с этой же ошибкой, когда проводил интеграционное тестирование БД, и сразу перешел к сути, не пытаясь объяснить мою конкретную проблему. Linq to Sql создаст SQL-запрос внутренне при использовании IQueryable, и в тот момент, когда вы выполняете метод для этого IQueryable, т. Е. ToList (), он выполняет этот запрос к базе данных. Так что в моем случае я присоединяюсь к методу, который возвращает IQueryable, но проверяет, чтобы вернуть результат, он пытается скомпилировать его в запрос sql, но созданный IQueryable не имеет внутреннего запроса SQL

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...