【问题标题】:Dynamic Linq creation动态 Linq 创建
【发布时间】:2011-10-17 13:48:03
【问题描述】:

我正在重写一个查询,该查询是为响应用户输入文本字段而创建的,以提供一些针对 SQL 注入攻击的保护。

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

我现在需要一种方法来根据用户是否在姓氏或名字文本输入框中选择/输入值来动态创建它?

任何指点将不胜感激

谢谢 罗杰

【问题讨论】:

    标签: sql linq dynamic


    【解决方案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 表和 firstNames 表之间没有连接条件?

    您可以动态构建查询(正如您所做的那样,我使用了 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();
    

    【讨论】:

    • 谢谢鲍勃,这非常有用。我已经部分沿着这条路线走了,但是当你指出一些表没有加入并且需要它们的地方完全加入时,我正在挣扎,我无法在 Linq 中轻松找到如何做到这一点。我遇到的主要问题是表的声明,以防没有添加额外的 where 子句。即用户只选择姓氏,因此没有将名字修饰符添加到 where 查询中。您的示例和 SelectMany 的使用让您大开眼界 - 非常感谢。
    • 如果您查看LinqPad,它可能会为您提供帮助,它可以为您的 linq 查询提供 lambda 语法,并为您提供与交叉连接相同的 selectmany。可以节省很多时间
    • 我已经简要了解了 LinqPad - 我需要付费版本才能真正受益吗?如果由于使用没有选择它而没有填充数组,则遇到了与 Nulls 相关的另一个问题!其中 (!surnameValues.Any() || surnameValues.Contains (sn.Surname)) && (!firstnameValues.Any() || firstnameValues.Contains (fn.FirstName)) 引发异常 - 我尝试添加 firstnameValues == null ||在 where 子句中,但它不起作用??
    • 您不需要付费版本,但它确实提供了有助于自动完成的智能感知。我已经更新了答案,因此它可以处理 firstnameValues 和 surnameValues 的空值
    猜你喜欢
    • 2015-10-01
    • 2011-02-18
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多