如何将List 转换为Sql In语句的SqlParameter?

我似乎对如何使用SqlParameter执行In语句感到困惑。 到目前为止,我有以下代码:

 cmd.CommandText = "Select dscr from system_settings where setting in @settings"; cmd.Connection = conn; cmd.Parameters.Add(new SqlParameter("@settings", settingList)); reader = cmd.ExecuteReader(); 

settingsListList 。 当cmd.ExecuteReader() ,由于无法将List映射到“已知的提供者类型”,因此出现ArgumentException

如何(安全地)使用SqlCommand执行In查询?

你可以尝试这样的事情:

 string sql = "SELECT dscr FROM system_settings WHERE setting IN ({0})"; string[] paramArray = settingList.Select((x, i) => "@settings" + i).ToArray(); cmd.CommandText = string.Format(sql, string.Join(",", paramArray)); for (int i = 0; i < settingList.Count; ++i) { cmd.Parameters.Add(new SqlParameter("@settings" + i, settingList[i])); } 

您似乎试图传递一个多值参数,SQL语法不会按预期执行。 您可能希望传递表值参数。

阅读: http : //www.sommarskog.se/arrays-in-sql.html#iter-list-of-strings

具体来说: http : //www.sommarskog.se/arrays-in-sql-2008.html#ListSqlDataRecord

 private static void datatable_example() { string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"}; DataTable custid_list = new DataTable(); custid_list.Columns.Add("custid", typeof(String)); foreach (string custid in custids) { DataRow dr = custid_list.NewRow(); dr["custid"] = custid; custid_list.Rows.Add(dr); } using(SqlConnection cn = setup_connection()) { using(SqlCommand cmd = cn.CreateCommand()) { cmd.CommandText = @"SELECT C.CustomerID, C.CompanyName FROM Northwind.dbo.Customers C WHERE C.CustomerID IN (SELECT id.custid FROM @custids id)"; cmd.CommandType = CommandType.Text; cmd.Parameters.Add("@custids", SqlDbType.Structured); cmd.Parameters["@custids"].Direction = ParameterDirection.Input; cmd.Parameters["@custids"].TypeName = "custid_list_tbltype"; cmd.Parameters["@custids"].Value = custid_list; using (SqlDataAdapter da = new SqlDataAdapter(cmd)) using (DataSet ds = new DataSet()) { da.Fill(ds); PrintDataSet(ds); } } } } 

我曾经使用自己的函数来创建像这样的参数:

 public void SomeDataFunction() { ArrayList params = GetParameters(someEntity); CommandObject.Parameters.AddRange(parameters.ToArray()); } public static ArrayList GetParameters(ISomeEntity entity) { ArrayList result = new ArrayList { OleDbUtility.NewDbParam("@Param1", OleDbType.Integer, , entity.Parameter1), OleDbUtility.NewDbParam("@Param2", OleDbType.VarChar, 9, entity.Parameter2), } } public static OleDbParameter NewDbParam(string parameterName, OleDbType dataType, int size, object value) { OleDbParameter result = new OleDbParameter(parameterName, dataType, size, string.Empty); result.Value = value; return result; } 

如果您使用的是Sql Server 2008或更高版本,则可以使用表值参数 – 这允许您将值表作为参数传入。 从.net中,您可以定义“结构化”类型的SqlParameter,并将值设置为实现IEnumerable的值。

有关示例,请参阅完整的MSDN参考: http : //msdn.microsoft.com/en-us/library/bb675163.aspx

使用XML,这种情况很快。 您可以将列表转换为XML并简单地传递一个字符串:

 CREATE TABLE #myTempTable ( Letter VARCHAR(20) ) INSERT INTO #myTempTable (Letter) VALUES ('A'), ('B') Declare @xml XML = 'ABC' Select * from #myTempTable Where Letter in (Select p.value('.', 'VARCHAR(40)') AS [Letter] from @xml.nodes('//a') as t(p)) DROP TABLE #myTempTable 

我通常将列表作为逗号分隔的字符串传递,然后使用表值函数将字符串“拆分”为一个表,然后我可以在另一个查询中使用该表。

 DECLARE @Settings TABLE (Sid INT) INSERT INTO @Settings(Sid) SELECT CAST(Items AS INT) FROM dbo.Split(@SettingsParameter, ',') 

除非您使用的是SQL Server 2008,否则我会使用表值参数。