如何将List <string>转换为Sql In语句的SqlParameter?</string>

时间:2010-12-21 18:50:54

标签: c# sql ado.net sqlcommand

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

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<string>。调用cmd.ExecuteReader()后,由于无法将ArgumentException映射到“已知提供商类型”,我会收到List<string>

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

6 个答案:

答案 0 :(得分:23)

您可以尝试这样的事情:

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]));
}

答案 1 :(得分:9)

您似乎试图传递多值参数,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);
         }
      }
   }
}

答案 2 :(得分:0)

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

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;
}

答案 3 :(得分:0)

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

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

答案 4 :(得分:-1)

使用XML,这种方案的速度非常快。您可以将列表转换为XML并简单地传递一个字符串:

CREATE TABLE #myTempTable
(   Letter VARCHAR(20) )

INSERT INTO  #myTempTable (Letter) VALUES ('A'), ('B')

Declare @xml XML = '<a>A</a><a>B</a><a>C</a>'

Select * from #myTempTable 
Where Letter in 
(Select p.value('.', 'VARCHAR(40)') AS [Letter] from @xml.nodes('//a') as t(p)) 

DROP TABLE #myTempTable

答案 5 :(得分:-2)

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

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

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