Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用SqlParameter创建ORDERBY子句_C#_Asp.net_Sql Server - Fatal编程技术网

C# 使用SqlParameter创建ORDERBY子句

C# 使用SqlParameter创建ORDERBY子句,c#,asp.net,sql-server,C#,Asp.net,Sql Server,我试图将对SQL语句中变量的所有引用移动到SqlParameter类,但是由于某种原因,此查询失败 string orderBy = Request.QueryString["OrderBy"]; //Fix up the get vars if (orderBy == null) orderBy = "name ASC"; string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORD

我试图将对SQL语句中变量的所有引用移动到SqlParameter类,但是由于某种原因,此查询失败

string orderBy = Request.QueryString["OrderBy"];
//Fix up the get vars
if (orderBy == null)
    orderBy = "name ASC";

string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY @OrderBy";
SqlCommand cmd = new SqlCommand(selectCommand, dataConnection);
cmd.Parameters.Add(new SqlParameter("@OrderBy", orderBy));

//Create the SQLDataAdapter instance
SqlDataAdapter dataCommand = new SqlDataAdapter(cmd);

//Create the DataSet instance
DataSet ds = new DataSet();
//Get data from a server and fill the DataSet  
dataCommand.Fill(ds);
这里是错误

System.Data.SqlClient.SqlException:由ORDER by number 1标识的SELECT项包含一个变量,作为标识列位置的表达式的一部分。仅当按引用列名的表达式排序时,才允许使用变量

它在这条线上失败了

dataCommand.Fill(ds);
使用SqlCommand是防止sql注入的方法。您更改order by的方式与在此上下文中使用sql注入的方式相同,因此不应允许这样做-参数用作常量,不能用作列或表名

您不必连接Sortb的内容,只需将其用作枚举,并根据其值连接您确信安全的内容即可。像这样:

If(orderBy == "some_column")
{
   selectColumn += "someColumn";
}
...

我找到了一个这样做的例子

您可以在案例结构中定义不同的排序顺序,并根据变量值适当执行它们:

  SELECT CompanyName,
         ContactName,
         ContactTitle

    FROM Customers

ORDER BY CASE WHEN @SortOrder = 1 THEN CompanyName
              WHEN @SortOrder = 2 THEN ContactName
         ELSE ContactTitle

我没有亲自测试,但它可以工作。你可以试试看。一个明显的缺点是您必须对所有order by语句进行编码。

您只是在串联字符串。更简单的办法是:

string orderBy = "name ASC";
string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY " + orderBy;
我假设您这样做是因为您让调用者决定排序字段/方向,因此orderBy是分隔的


正如错误消息间接暗示的那样,参数将在WHERE子句中使用,例如WHERE someColumn=@someValue等。

您确实有三个选项

1使用数据视图对结果集进行排序

2如果知道可以排序的列,可以测试字符串,然后使用,然后选择顺序。e、 g

例如,这将起作用

DECLARE @orderby varchar(255)
SET @orderby = 'Name ASC'

SELECT [Your Column here ]FROM sys.tables 
ORDER BY    
   case WHEN @orderby = 'Name ASC' Then name ELSE null END ASC,
   case WHEN @orderby = 'Name DESC' Then name ELSE null END DESC,
   CASE WHEN @orderby = 'Object_id ASC' then object_id ELSE null END ASC,
   CASE WHEN @orderby = 'Object_id DESC' then object_id ELSE null END DESC
3最后一个选项是在C代码中执行与2相同的操作。只需确保您不只是从用户输入中添加ORDERBY子句,因为这对SQL注入是无效的

这是安全的,因为OrderBy Url参数名称Desc;DROP table USERS将被忽略

string SafeOrderBy = "";
string orderBy = Request.QueryString["OrderBy"];
//Fix up the get vars
if (orderBy == null)
    orderBy = "name ASC";

if (orderby == "name Desc")
{
     SafeOrderBy == "name Desc"
}


string selectCommand = "SELECT cat_id AS id, cat_name AS name FROM table_name ORDER BY "
selectCommand  += SafeOrderBy ;

我遇到了与您相同的问题,但是列出的解决方案无法使用,因为我的可能排序列是模型的属性之一,这意味着如果模型很大,那么if语句就太多了。 我对这个相关问题的解决方案是使用反射。比如:

class MyModel {
    public string MyField1 { get; set; }
    public string MyField2 { get; set; }
    // ...
}

//...
using System.Reflection;
// sortBy = "MyField1"
// sortDirection = "Asc";
var sql = "SELECT FROM foo WHERE bar=baz ORDER BY ";
foreach (var prop in typeof(MyModel).GetProperties())
{
    if (sortBy.Equals(prop.Name))
    {
        sql += (prop.Name + (sortDirection.Value.Equals("Asc") ? " ASC" : " DESC"));
        break;
    }
}

此解决方案的好处是,无论我的模型如何变化,此代码将支持按其任何属性排序,因此也不需要更改。

orderBy的值是多少?感谢我修复了在我的代码中,您是否尝试使用列的确切名称而不是别名?因此,我无法让客户端指定如何对这些数据进行排序。ORDERBY字符串来自客户机提供的get变量。那么,如果orderBy子句可以在不同的查询之间进行更改,我将如何添加该子句呢?好的,但是orderBy命令没有进行属性转义,这使我面临sql注入。我应该使用System.Security.SecurityElement.EscapeorderBy,然后将其附加到selectCommand中吗?当您希望处理值时,转义有什么意义?您希望排序依据的唯一值是应计算的列名称或表达式。顺便说一句,你必须亲自检查它是否安全我意识到这是一个查询注入风险。你应该经常检查你的输入。出于这个原因,我更喜欢参数化查询或存储过程,而不是临时查询。是的,这正是我试图阻止的。由于这些数据是通过get var从用户处传入的,所以我想确保查询将受到保护。更好的选择是使用System.Security.SecurityElement.Escape;方法?我也在看那篇文章。我想要一个更简单的方法,但我认为这可能是正确的方法。