LINQ to Entities中的动态查询

时间:2010-09-09 16:16:45

标签: c# linq-to-entities

使用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 个答案:

答案 0 :(得分:3)

问题是您没有使用Where子句的结果。只需调用Where并忽略返回值,就不会改变query中的内容。加入它可能有点棘手,但没有它们很容易:

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

如果您可以提供有关联接需要做什么的更多信息,我们也可以对此进行排序。

请注意,据我所知,您的动态SQL版本很容易受到SQL注入攻击,顺便说一下 - 使用LINQ的情况并非如此。

答案 1 :(得分:0)

你实际上是在做这件事。请记住,当您请求数据时,将生成并执行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);
}