2011-08-01 88 views
1

我正在重寫爲響應用戶輸入到文本字段而創建的查詢,以便爲SQL注入攻擊提供一些保護。動態Linq創建

SELECT DISTINCT (FileNameID) FROM SurNames WHERE Surname IN 
('Jones','Smith','Armitage') 
AND FileNameID IN (SELECT DISTINCT (FileNameID) FROM FirstNames WHERE FirstName 
IN ('John','William')) 

在這個過程中最多可以涉及3個其他表。 參數列表最多可以有50-100個條目,因此構建參數化查詢非常繁瑣和麻煩。

我想創建一個Linq查詢,它應該照顧參數化並提供我需要的保護。

這給了我什麼,我需要

var surnameValues = new[] { "Jones","Smith","Armitage" }; 
    var firstnameValues = new[] { "John","William" }; 

    var result = (from sn in db.Surnames 
       from fn in db.FirstNames 
       where surnameValues.Contains(sn.Surname) && 
       firstnameValues.Contains(fn.FirstName) 
       select fn.FileNameID).Distinct().ToArray(); 

我現在需要一種方法來動態創建這個取決於用戶是否選擇/輸入值的姓氏或名字文本輸入框?

任何指針將受到歡迎

感謝 羅傑

回答

1

你可以所有的邏輯合併到查詢;

var surnameValues = new[] { "Jones","Smith","Armitage" }; 
var firstnameValues = null; 

// Set these two variables to handle null values and use an empty array instead 
var surnameCheck= surnameValues ?? new string[0]; 
var firstnameCheck= firstnameValus ?? new string[0]; 

var result = (from sn in db.Surnames 
      from fn in db.FirstNames 
      where 
      (!surnameCheck.Any() || surnameCheck.Contains(sn.Surname)) && 
      (!firstnameCheck.Any() || firstnameCheck.Contains(fn.FirstName)) 
      select fn.FileNameID).Distinct().ToArray(); 

您的查詢似乎沒有Surnames表和firstName表之間的連接條件?

你可以動態生成查詢(如你似乎做我CROSS JOIN我用SelectMany

var query=db.Surnames.SelectMany(sn=>db.FirstNames.Select (fn => new {fn=fn,sn=sn})); 
if (surnameValues!=null && surnameValues.Any()) query=query.Where(x=>surnameValues.Contains(x.sn.Surname)); 
if (firstnameValues !=null && firstnameValues.Any()) query=query.Where(x=>firstnameValues.Contains(x.fn.FirstName)); 
var result=query.Select(x=>x.fn.FileNameID).Distinct(); 
+0

感謝鮑勃,這是非常有用的。我已經部分沿着這條路線走下去了,但是正如你指出的那樣,一些表格沒有加入,需要一個完整的連接,我不能輕易地在Linq找到如何做。我遇到的主要問題是在沒有附加where子句時添加表格的聲明。即用戶只選擇姓氏,所以沒有firstname修飾符添加到where查詢。 你的例子和SelectMany的使用讓人大開眼界 - 非常感謝。 – RogerDodge

+0

有一件事可以幫助你,如果你看看[LinqPad](http://www.linqpad.net)它可以給你linq查詢的lambda語法,並且會爲你提供相同的交叉連接selectmany 。可以節省很多時間 –

+0

我已經簡單地查看了LinqPad - 我需要付費版本才能真正適合嗎? 已經碰到另一個問題與空值如果數組沒有被填充,因爲使用沒有選擇它! 其中&& 拋出異常(surnameValues.Any()|| surnameValues.Contains (sn.Surname)!)(firstnameValues.Any()|| firstnameValues.Contains (fn.FirstName)!) - 我已嘗試添加 firstnameValues == null ||在where子句中,但它不起作用? – RogerDodge