在通过ADO.NET与SQL进行数据交互时,为了防止SQL注入,一般采用参数化的方式,而SqlParameter对应的构造函数如下
// 摘要: // 初始化 System.Data.SqlClient.SqlParameter 类的新实例。 public SqlParameter(); // // 摘要: // 用参数名称和新 System.Data.SqlClient.SqlParameter 的一个值初始化 System.Data.SqlClient.SqlParameter // 类的新实例。 // // 参数: // parameterName: // 要映射的参数的名称。 // // value: // 一个 System.Object,它是 System.Data.SqlClient.SqlParameter 的值。 public SqlParameter(string parameterName, object value); // // 摘要: // 用参数名称和数据类型初始化 System.Data.SqlClient.SqlParameter 类的新实例。 // // 参数: // parameterName: // 要映射的参数的名称。 // // dbType: // System.Data.SqlDbType 值之一。 // // 异常: // System.ArgumentException: // dbType 参数中提供的值为无效的后端数据类型。 public SqlParameter(string parameterName, SqlDbType dbType); // // 摘要: // 用参数名称、System.Data.SqlDbType 和大小初始化 System.Data.SqlClient.SqlParameter 类的新实例。 // // 参数: // parameterName: // 要映射的参数的名称。 // // dbType: // System.Data.SqlDbType 值之一。 // // size: // 参数的长度。 // // 异常: // System.ArgumentException: // dbType 参数中提供的值为无效的后端数据类型。 public SqlParameter(string parameterName, SqlDbType dbType, int size); // // 摘要: // 用参数名称、System.Data.SqlDbType、大小和源列名称初始化 System.Data.SqlClient.SqlParameter // 类的新实例。 // // 参数: // parameterName: // 要映射的参数的名称。 // // dbType: // System.Data.SqlDbType 值之一。 // // size: // 参数的长度。 // // sourceColumn: // 源列的名称。 // // 异常: // System.ArgumentException: // dbType 参数中提供的值为无效的后端数据类型。 public SqlParameter(string parameterName, SqlDbType dbType, int size, string sourceColumn); // // 摘要: // 用参数名称、参数的类型、参数的大小、System.Data.ParameterDirection、参数的精度、参数的小数位数、源列、要使用的 System.Data.DataRowVersion // 和参数的值初始化 System.Data.SqlClient.SqlParameter 类的新实例。 // // 参数: // parameterName: // 要映射的参数的名称。 // // dbType: // System.Data.SqlDbType 值之一。 // // size: // 参数的长度。 // // direction: // System.Data.ParameterDirection 值之一。 // // isNullable: // 如果字段的值可为 null,则为 true;否则为 false。 // // precision: // 要将 System.Data.SqlClient.SqlParameter.Value 解析为的小数点左右两侧的总位数。 // // scale: // 要将 System.Data.SqlClient.SqlParameter.Value 解析为的总小数位数。 // // sourceColumn: // 源列的名称。 // // sourceVersion: // System.Data.DataRowVersion 值之一。 // // value: // 一个 System.Object,它是 System.Data.SqlClient.SqlParameter 的值。 // // 异常: // System.ArgumentException: // dbType 参数中提供的值为无效的后端数据类型。 [EditorBrowsable(EditorBrowsableState.Advanced)] public SqlParameter(string parameterName, SqlDbType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value); // // 摘要: // 初始化 System.Data.SqlClient.SqlParameter 类的一个新实例,该类使用参数名、参数的类型、参数的长度、方向、精度、小数位数、源列名称、System.Data.DataRowVersion // 值之一、用于源列映射的布尔值、SqlParameter 的值、此 XML 实例的架构集合所在的数据库的名称、此 XML 实例的架构集合所在的关系架构以及此参数的架构集合的名称。 // // 参数: // parameterName: // 要映射的参数的名称。 // // dbType: // System.Data.SqlDbType 值之一。 // // size: // 参数的长度。 // // direction: // System.Data.ParameterDirection 值之一。 // // precision: // 要将 System.Data.SqlClient.SqlParameter.Value 解析为的小数点左右两侧的总位数。 // // scale: // 要将 System.Data.SqlClient.SqlParameter.Value 解析为的总小数位数。 // // sourceColumn: // 源列的名称。 // // sourceVersion: // System.Data.DataRowVersion 值之一。 // // sourceColumnNullMapping: // 如果源列可以为 null,则为 true;如果不可以为 null,则为 false。 // // value: // 一个 System.Object,它是 System.Data.SqlClient.SqlParameter 的值。 // // xmlSchemaCollectionDatabase: // 此 XML 实例的架构集合所在的数据库的名称。 // // xmlSchemaCollectionOwningSchema: // 包含此 XML 实例的架构集合的关系架构。 // // xmlSchemaCollectionName: // 此参数的架构集合的名称。 public SqlParameter(string parameterName, SqlDbType dbType, int size, ParameterDirection direction, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, object value, string xmlSchemaCollectionDatabase, string xmlSchemaCollectionOwningSchema, string xmlSchemaCollectionName);
1、绝对不要直接用 new SqlParameter(“@Test”,0),具体原因在msdn上有
2、查询时,对于字符串,会出现一些你意想不到的事情,以下是真实案例,亲身经历(注:数据库字段均为varchar,两个参数的构造函数默认会设置SqlDbType为nvarchar)
a) 根据用户名查询相关信息,简单的一个where userName=@UserName,数据量不大,查询时间需要几秒,直接在SQL查询分析器里面毫秒,具体原因可以见这里
b) Like查询,假定要查询%L%,有些包含L的能被查询出来,有些却查不出来,Why?好吧,暂时我还没找到相关的书面解释,但猜测还是跟a同样的原因,而对于此问题的推断依据是:能查询出来的字符串长度都是在几百以内,而查不出来的字符串都是非常长的字符串,虽然没具体统计过,但长度至少在4000以上(nvarchar后面为具体数字时最大只能4000)
PS:MSSQL的隐式转换遵循向上转换原则,类似C#,即(long)50与(int)50进行比较时,(int)50会被隐式转化成(long)50
注:虽然此处是以MSSQL作为例子,但相信同样的问题在其它关系型数据库中也会存在,所以最好还是不要偷懒,毕竟
new SqlParameter("@Test",0)与
var param = new SqlParameter("@Test", SqlDbType.Int); param.Value = 0;相比,其实也没少多少代码是不是
其实没搞懂为啥微软没提供个如下的构造函数呢
public SqlParameter(string parameterName,SqlDbType dbType,object value);