Динамические запросы в LINQ to Entities - PullRequest
0 голосов
/ 09 сентября 2010

Используя хранимые процедуры TSQL, динамические запросы были простыми.Например, скажем, у меня было приложение для составления отчетов, которое опционально запрашивало архивные записи.Хранимая процедура будет выглядеть так:

DECLARE @sql nvarchar(MAX)
DECLARE @join nvarchar(MAX)
DECLARE @where nvarchar(MAX)

IF @optionalvar1 IS NOT NULL
    SET @where = COALESCE(@where, '') +
    'AND SomeColumn = ' + @optionalvar1 + ' '

IF @optionalvar2 IS NOT NULL
    BEGIN
    SET @join = COALESCE(@join, '') +
   'LEFT JOIN SomeTable s 
    ON st.Column = s.Column '

    SET @where = COALESCE(@where, '') +
    'AND s.SomeColumn = ' + @optionalvar2 + ' '
    END

SET @sql =
'
SELECT
    *
FROM
    StaticTable st
    ' + COALESCE(@join, '') + '
WHERE
    1=1
    ' + COALESCE(@where, '') + '
'

Запрет на любые глупые опечатки, вот как я делал динамические запросы раньше.Для каждого нового необязательного параметра я добавляю еще один условный блок и добавляю необходимый код соединения и кода (и адаптирую модель, если мне нужно также добавить порядок и т. Д.).Я пытаюсь выяснить, как это сделать в сущностях, но у меня трудные времена.

Большинство найденных мной ссылок (в частности, http://naspinski.net/post/Writing-Dynamic-Linq-Queries-in-Linq-to-Entities.aspx) показывают, как искатьдинамически изменяемая строка, использующая этот бит кода:

var data = ctx.table.Where(b => b.branch_id == 5 || b.display == "Hello");

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

Я надеялся, что смогу сделать что-то простое, например:

    var query =
        (from t in ctx.Table
         select t);

    if (optionalvar1)
    {
        query = query.Join('etc');
        query = query.Where('etc');
    }

Но не добился большого прогресса (не могу понять синтаксис того, чтобы заставить ихделай то, что я хочу.

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

Ответы [ 2 ]

3 голосов
/ 09 сентября 2010

Проблема в том, что вы не используете результат предложения Where.Просто вызов Where и игнорирование возвращаемого значения не изменит то, что в query.С объединениями это может быть несколько сложно, но без них это просто:

if (someCondition)
{
    query = query.Where(x => x.Text == "Some value");
}

Если вы можете дать больше информации о том, что должны делать ваши объединения, мы, вероятно, тоже можем разобраться.

Обратите внимание, что, насколько я вижу, ваша динамическая версия SQL была бы уязвима для атак с использованием SQL-инъекций, кстати, что не так при использовании LINQ.

0 голосов
/ 09 сентября 2010

вы делаете это правильно на самом деле.помните, что sql будет сгенерирован и выполнен при запросе данных.

вы можете сделать что-то вроде

var v = (from p in Context.User select p);

if (txtLastName.Text.Lenght > 0)
{
    v = (from p in v where p.LastName.Contains(txtLastName.Text) select p);
}

if (txtCity.Text.Lenght > 0)
{
    v = (from p in v
         join q in Context.City on p.City equals q.CityId
         where q.CityName.Contains(txtCity.Text) select p);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...