2011-08-01 86 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