2010-09-09 96 views
0

使用TSQL存儲過程,動態查詢變得十分簡單。例如,假設我有一個報告應用程序,可以選擇要求存檔記錄。存儲過程看起來像這樣:LINQ to Entities中的動態查詢

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, '') + ' 
' 

除了任何愚蠢的錯別字,這就是我以前做過的動態查詢。對於每個新的可選參數,我添加另一個條件塊並添加必要的連接和代碼(如果需要添加排序等,則調整模型)。我試圖找出如何在Entities中做到這一點,但是我有一段艱難的時間。

我發現大多數鏈接(特別是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"); 

我不認爲這部作品在我的例子,因爲我需要動態地添加額外的正數,其中的條款,並根據在傳遞什麼變量可能加入

我希望我可以做喜歡的事簡單:

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

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

但是沒有取得太大的進展(不能完全弄清楚要麼讓他們做我想做的事情的語法。

任何想法?我接近這個錯誤嗎?有更好,更簡單的解決方案嗎?我知道在一天結束時,我總是可以有一組條件檢查每個可能的組合,然後在該塊中生成整個LINQ查詢,但是需要的複製麪食的數量令人沮喪。

回答

3

問題是,您沒有使用Where子句的結果。只需撥打Where並忽略返回值,根本不會改變query中的內容。隨着加入它可能是有點棘手,但沒有他們很容易:

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

如果你能提供有關你的加入需要做更多的信息,我們可以大概那種出了。

請注意,據我所知,您的動態SQL版本將容易受到SQL注入攻擊,順便說一句 - 這不是使用LINQ的情況。

+0

對不起,不能設置查詢= query.Where更是一個錯字比什麼的。我的主要問題是如何在.Where位內部表達我的查詢。我不能只使用對象'x' - 這是一個包含我的查詢的最終結果的POCO。然而,在大多數情況下,我需要做的是在涉及查詢的其他表中添加where子句,但不一定返回到最終對象中。我會更新這個問題來澄清。 (另外,傳入動態SQL的變量來源於.NET中的參數化查詢,並通過sp_executesql得到執行 - 應該沒問題(?)。) – rake 2010-09-09 16:29:09

+2

@rake:它看起來像它只是一個POCO,但是LINQ to Entities會實際上是將它們轉換成SQL。如果沒有一個具體的例子,要求在查詢的其餘部分中不存在的事情很難說清楚。不,我不相信你的動態SQL從SQL注入攻擊是安全的,只是因爲它們在.NET中被參數化。每個參數的值直接插入到最終的SQL中。我強烈建議你嘗試一下。只需要一個包含單引號的查詢就足以讓您瞭解正在發生的事情...... – 2010-09-09 16:48:03

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