C# 修复SQL参数化

C# 修复SQL参数化,c#,.net,sqlclient,C#,.net,Sqlclient,我在更新一些SQL查询以使用参数而不是字符串连接时遇到了一些问题。没什么特别难的,我只是想弄清楚我错过了什么或者做错了什么 结束查询应该如下所示 SELECT [DeviceSeq], [DeviceName], [SerialNumber], [Premise], [InsertDate], [VersionNumber], [LastUpdateDate], [IsDeleted] FROM [ITAM].[dbo].[AllDevices] WHERE DeviceName LIKE '%

我在更新一些SQL查询以使用参数而不是字符串连接时遇到了一些问题。没什么特别难的,我只是想弄清楚我错过了什么或者做错了什么

结束查询应该如下所示

SELECT [DeviceSeq], [DeviceName], [SerialNumber], [Premise], [InsertDate], [VersionNumber], [LastUpdateDate], [IsDeleted] FROM [ITAM].[dbo].[AllDevices] WHERE DeviceName LIKE '%InputFilter%' OR SerialNumber = 'InputFilter'
以前我是这样做的,它会返回我期望的结果

command.CommandText = "SELECT [DeviceSeq], [DeviceName], [SerialNumber], [Premise], [InsertDate], [VersionNumber], [LastUpdateDate], [IsDeleted] FROM [ITAM].[dbo].[AllDevices] WHERE DeviceName LIKE '%@" + filter + "%' OR SerialNumber = '" + filter + "'";
但我想做的是这样。但是,每次我尝试这样做(参数化)时,它都会返回0个结果或错误,具体取决于我尝试和格式化的方式

List<dynamic> hosts = new List<dynamic>();
using (SqlCommand command = conn.CreateCommand())
{
    command.CommandText = "SELECT [DeviceSeq], [DeviceName], [SerialNumber], [Premise], [InsertDate], [VersionNumber], [LastUpdateDate], [IsDeleted] FROM [ITAM].[dbo].[AllDevices] WHERE DeviceName LIKE '%@filter%' OR SerialNumber = '@filter'";

    var param = new SqlParameter("filter", System.Data.SqlDbType.VarChar);
    param.Value = filter;
    command.Parameters.Add(param);


    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            dynamic h = new ITAMHost()
            {
                DeviceSeq = reader[0].ToString(),
                DeviceName = reader[1].ToString(),
                SerialNumber = reader[2].ToString(),
                Premise = reader[3].ToString(),
                InsertDate = reader[4].ToString(),
                VersionNumber = reader[5].ToString(),
                LastUpdateDate = reader[6].ToString(),
                IsDeleted = reader[7].ToString(),
            };
            hosts.Add(h);
        }
    }
}

List hosts=new List();
使用(SqlCommand=conn.CreateCommand())
{
command.CommandText=“从[ITAM].[dbo].[AllDevices]中选择[DeviceSeq]、[DeviceName]、[SerialNumber]、[Premise]、[InsertDate]、[VersionNumber]、[LastUpdateDate]、[IsDeleted],其中DeviceName如“%@filter%”或SerialNumber=“@filter%”;
var param=new-SqlParameter(“filter”,System.Data.SqlDbType.VarChar);
参数值=过滤器;
命令.Parameters.Add(param);
使用(var reader=command.ExecuteReader())
{
while(reader.Read())
{
动态h=新ITAMHost()
{
DeviceSeq=读取器[0]。ToString(),
DeviceName=读取器[1]。ToString(),
SerialNumber=读取器[2]。ToString(),
Premise=读取器[3]。ToString(),
InsertDate=读取器[4]。ToString(),
VersionNumber=读取器[5]。ToString(),
LastUpdateDate=读取器[6]。ToString(),
IsDeleted=读取器[7]。ToString(),
};
添加(h);
}
}
}

您好,请尝试如下更改您的代码:

List<dynamic> hosts = new List<dynamic>();
using (SqlCommand command = conn.CreateCommand())
{
    command.CommandText = "SELECT [DeviceSeq], [DeviceName], [SerialNumber], [Premise], [InsertDate], [VersionNumber], [LastUpdateDate], [IsDeleted] FROM [ITAM].[dbo].[AllDevices] WHERE DeviceName LIKE @filter OR SerialNumber = @filter";

    var param = new SqlParameter("filter", System.Data.SqlDbType.VarChar);
    param.Value = "%YOUR_FILTER_VALUE%";
    command.Parameters.Add(param);

    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            dynamic h = new ITAMHost()
            {
                DeviceSeq = reader[0].ToString(),
                DeviceName = reader[1].ToString(),
                SerialNumber = reader[2].ToString(),
                Premise = reader[3].ToString(),
                InsertDate = reader[4].ToString(),
                VersionNumber = reader[5].ToString(),
                LastUpdateDate = reader[6].ToString(),
                IsDeleted = reader[7].ToString(),
            };
            hosts.Add(h);
        }
    }
}
List hosts=new List();
使用(SqlCommand=conn.CreateCommand())
{
command.CommandText=“从[ITAM].[dbo].[AllDeviceName]中选择[DeviceSeq]、[DeviceName]、[SerialNumber]、[Premise]、[InsertDate]、[VersionNumber]、[LastUpdateDate]、[IsDeleted],其中DeviceName如@filter或SerialNumber=@filter”;
var param=new-SqlParameter(“filter”,System.Data.SqlDbType.VarChar);
参数值=“%YOUR_FILTER_Value%”;
命令.Parameters.Add(param);
使用(var reader=command.ExecuteReader())
{
while(reader.Read())
{
动态h=新ITAMHost()
{
DeviceSeq=读取器[0]。ToString(),
DeviceName=读取器[1]。ToString(),
SerialNumber=读取器[2]。ToString(),
Premise=读取器[3]。ToString(),
InsertDate=读取器[4]。ToString(),
VersionNumber=读取器[5]。ToString(),
LastUpdateDate=读取器[6]。ToString(),
IsDeleted=读取器[7]。ToString(),
};
添加(h);
}
}
}

参数不是内联文本替换。您正在将
DeviceName
与包含实际文本“@filter”(和
SerialNumber
等于“@filter”)的值进行比较,而不是将
@filter
参数所包含的值进行比较。您必须像@filter一样使用
DeviceName,并在参数值中包含通配符,尽管这可能导致拒绝服务攻击,其中输入是一种非常复杂的模式,引擎需要很长时间才能执行。然后您必须禁止输入中的通配符或对其进行转义。@madreflection:谢谢!我现在明白了。谢谢!在这和@madreflection的答案之间,我现在明白了。一定要考虑到通配符的转义。。。LIKE除了对零个或多个字符使用百分比外,还对单个字符使用下划线,因此将
\
替换为
[\]
,将
%
替换为
[%]
在包装
%
以匹配这些字符之前,不要将它们视为通配符。这对于
序列号的相等性检查不起作用,因为它现在具有%通配符值。相反,可以在查询中添加通配符,如下所示
,其中DeviceName类似“%”++@filter++“%”或SerialNumber=@filter
。或者,如果要将通配符添加到参数中,则需要两个参数。