C# 使用SqlParameter创建ORDERBY子句
我试图将对SQL语句中变量的所有引用移动到SqlParameter类,但是由于某种原因,此查询失败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
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;方法?我也在看那篇文章。我想要一个更简单的方法,但我认为这可能是正确的方法。