有数组查询条件比如Ids=int?[]{1,2,3,4},这样再拼接SQL语句的时候写成id=@Ids,
SqlParameters.Add(new SqlParameter("@Ids",Ids)),代码层面是没错,但是查询数据库时会报错。
{"不存在从对象类型 System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][] 到已知的托管提供程序本机类型的映射。"}
找了很多解决方法,个人觉得比较好的是【为每一个参数生成一个参数实现where in 参数化】
可以循环一下数组,然后sql语句拼接成id in (@Ids1,@Ids2,@Ids3,@Ids4),然后参数也是多个,
SqlParameters.Add(new SqlParameter("@Ids1",1));
SqlParameters.Add(new SqlParameter("@Ids2",2));
SqlParameters.Add(new SqlParameter("@Ids3",3));
SqlParameters.Add(new SqlParameter("@Ids4",4));
这样就解决了。
网上还看到一种用临时表的解决方法,由于需要创建临时表,会带来额外的IO开销,若查询频率很高,参数不多的话建议使用上面的方法,如果参数很多可以使用临时表的方法性能很好,方法如下:
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
string sql = @"
declare @Temp_Variable varchar(max)
create table #Temp_Table(Item varchar(max))
while(LEN(@Temp_Array) > 0)
begin
if(CHARINDEX(',',@Temp_Array) = 0)
begin
set @Temp_Variable = @Temp_Array
set @Temp_Array = ''
end
else
begin
set @Temp_Variable = LEFT(@Temp_Array,CHARINDEX(',',@Temp_Array)-1)
set @Temp_Array = RIGHT(@Temp_Array,LEN(@Temp_Array)-LEN(@Temp_Variable)-1)
end
insert into #Temp_Table(Item) values(@Temp_Variable)
end
select * from Users(nolock) where exists(select 1 from #Temp_Table(nolock) where #Temp_Table.Item=Users.UserID)
drop table #Temp_Table";
comm.CommandText = sql;
comm.Parameters.Add(new SqlParameter("@Temp_Array", SqlDbType.VarChar, -1) { Value = "1,2,3,4" });
comm.ExecuteNonQuery();
}