Entity Framework использует CompiledQuery, но допускает значения фильтра времени выполнения - PullRequest
0 голосов
/ 12 мая 2011

Я пытаюсь провести рефакторинг громоздкого слоя данных LINQ-to-SQL с помощью структуры сущностей.Схема базы данных за моделью большая, и типичный запрос может содержать от 20 до 30 включений.EF генерирует массивные операторы SQL для таких запросов, самые большие из которых до сих пор были 4k строк, но они по-прежнему выполняются своевременно, так что это не проблема.

Проблема в том, что EF требуется много времени, до 4 или 5 секунд, чтобы сгенерировать запрос.Чтобы преодолеть это, я использовал CompileQuery.Проблема в том, что существующий слой данных L2S имеет множество фильтров, которые можно применять к запросу в зависимости от пользовательского ввода.Одно значение в этих фильтрах должно быть установлено во время выполнения.

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

public static class DataLayer
{
    static Func<MyEntities, int, IQueryable<Prescription>> compiledQuery;

    static int? FilterHpID;
    static Expression<Func<Prescription, bool>> filter1 = x => (FilterHpID == null || x.Prescriber.HPID == FilterHpID);

    static DateTime? FilterDateTime;
    static Expression<Func<Prescription, bool>> filter2 = x => (FilterDateTime == null || x.DateTimeDispensed > FilterDateTime);

    public static List<Prescription> Get(int patientID, int? hpID, DateTime? dispensed)
    {
        FilterHpID = hpID;
        FilterDateTime = dispensed;

        if (compiledQuery == null)
        {
            compiledQuery = System.Data.Objects.CompiledQuery.Compile((MyEntities entities, int id) =>
                        (from pre in entities.Prescription
                         where pre.PatientID == id
                         select pre)
                         .Where(filter1)
                         .Where(filter2));
        }

        using (MyEntities entities = new MyEntities())
        {
            return compiledQuery(entities, patientID).ToList();
        }
    }
}

Есть ли способ, которым я могу включитьмои выражения фильтра в скомпилированном запросе И возможность устанавливать значения в выражениях фильтра при выполнении запроса?

Ответы [ 2 ]

0 голосов
/ 13 мая 2011

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

Цель приведенного ниже кода невозможна ни в какой форме или форме.

static Expression<Func<Prescription, bool>> filter1 = x => (FilterHpID == null || x.Prescriber.HPID == 1);

compiledQuery = System.Data.Objects.CompiledQuery.Compile((MyEntities entities, int id) =>
                    (from pre in entities.Prescription
                     where pre.PatientID == id
                     select pre)
                     .Where(filter1));

Мы собираемся перейти к рассмотрению использования представлений базы данных, чтобы обойти необходимость в первую очередь использовать скомпилированные запросы. Если запросы L2E не нужно компилировать, чтобы избежать почти двухсекундной задержки, можно добавить фильтры выражений многократного использования.

0 голосов
/ 12 мая 2011

Фильтры должны быть частью скомпилированного запроса, и после этого вы можете установить их при вызове запроса. Я думаю, что вы можете использовать что-то вроде:

public static IQueryable<Prescription> Filter1(this IQueryale<Prescription> query, 
    DateTime? param)
{
    return query.Where(x => (param == null || x.Prescriber.HPID == param));
}

Тогда вы сможете определить ваш скомпилированный запрос как:

 compiledQuery = System.Data.Objects.CompiledQuery
                       .Compile((MyEntities entities, int id, DateTime? param) =>
                           (from pre in entities.Prescription
                            where pre.PatientID == id
                            select pre)
                           .Filter1(param));

Он работает с обычными запросами, но я никогда не пробовал его в скомпилированных запросах. Если это не работает, вы должны поместить выражение фильтра непосредственно в скомпилированный запрос:

 compiledQuery = System.Data.Objects.CompiledQuery
                       .Compile((MyEntities entities, int id, DateTime? param) =>
                           (from pre in entities.Prescription
                            where pre.PatientID == id
                            select pre)
                           .Where(x => (param == null || x.Prescriber.HPID == param));
...