如何将多个整数参数插入查询?
How to insert multiple integer parameters into query?
网站用户可以输入搜索条件查询订单。用户、状态、状态、OrderID 等
网站与 API 通信。查询参数在 header 中,因此我假设它们以字符串形式出现。 API 通过 Dapper 与 Access 通信。
对于某些条件,他们可以发送多个值。所以我想使用 "IN" 子句。
where UserID in (150, 3303, 16547)
Dapper 处理得很好。
connection.Query<int>("select * from table where Id in @Ids", new { Ids = new int[] { 1, 2, 3 } });
这适用于 MS-Access
SELECT top 100 * from Orders where UserID in (150, 30330)
但这只有在值为整数时才有效。 String 和 Strings 在 Access 中都给出 "Data type mismatch in criteria expression"。
SELECT top 100 * from Orders where UserID in ("150", "30330") // two strings
SELECT top 100 * from Orders where UserID in ("150, 30330") // single string
这可能是巧合,但我看到的所有例子都是整数。如果您未指定大小,Access 会在字符串上引发错误。使用 DynamicParameters 可以轻松指定大小。
但是当字段是一个 int 时,我的 dapper 代码给出了同样的错误(条件表达式中的数据类型不匹配):
var paramlist = new DynamicParameters();
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
paramlist.Add("userId", userId, DbType.String, ParameterDirection.Input, 50);
sbWhere.AppendFormat("AND CustFID in (?) ", paramIndex++);
}
所以我假设问题是我告诉它参数是一个字符串。
但是,如果我将参数设置为 int,则它不会采用具有多个值的字符串。相反,如果我在字符串中包含 (),它会抱怨 'in' 子句中缺少 parens。
我尝试将数字字符串拆分为数组 and/or 列表。
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
var userIds = userId.Split(','); //.ToList(); fails, can't map to native type
paramlist.Add("userId", userIds, DbType.String, ParameterDirection.Input, 1000);
if (userIds.Length > 1) {
sbWhere.AppendFormat("AND CustFID in @userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = @userId ", paramIndex++);
}
}
并给出“:不存在从 object 类型 System.String[] 到已知托管提供程序本机类型的映射。”我说的参数是int32还是string.
更新:
可能有多个搜索条件,所以我使用 DynamicParameters。
这是我尝试实现 Palle Due 的想法。
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
// var userIds = userId.Split(',').Select(i => Int32.Parse(i)).ToList();// fails, can't map to native type
IEnumerable<int> userIds = userId.Split(',').Select<string, int>(int.Parse);
paramlist.Add("userId", userIds, DbType.Int32, ParameterDirection.Input);
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in @userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = @userId ", paramIndex++);
}
}
using (IDbConnection conn = Connection) {
string sQuery = string.Format("SELECT {0} FROM vwweb_Orders {1}", columns, where);
conn.Open();
var result = await conn.QueryAsync<Order>(sQuery, paramlist);
return result.ToList();
}
投掷
Message: System.AggregateException : One or more errors occurred. (Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.)
----> System.InvalidCastException : Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.
----> System.InvalidCastException : Object must implement IConvertible.
@Dai 链接到的 github 页面指定 Dapper 列表支持仅适用于 IEnumerable<int>
。
但据我了解,您的 UserID
是一个整数,所以我不明白您为什么要输入字符串。您需要获取用户输入的字符串并将其转换为IEnumerable<int>
。做这样的事情:
IEnumerable<int> userIDs = (userId?? "").Split(',').Select<string, int>(int.Parse);
var result = connection.Query<int>("SELECT TOP 100 * FROM Orders WHERE UserID IN @Ids", new { Ids = userIDs });
您可能想对其应用一些输入检查,并且您可能还想重新考虑使用 Access 作为网站的 "database"。这不是它的本意。
我放弃了。 Dapper 应该能够处理这个问题,但这是一个较新的功能,所以...
我刚刚自己构建了 IN 子句。
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in ( ");
int paramCnt = 0;
foreach (int id in userIds) {
sbWhere.AppendFormat("?, "); // Access doesn't mind a trailing ,
paramlist.Add("userId" + paramCnt.ToString(), id, DbType.Int32, ParameterDirection.Input);
paramCnt++;
}
sbWhere.AppendFormat(") ");
} else {
sbWhere.AppendFormat("AND CustFID = ? ");
paramlist.Add("userId", userIds.ToArray<int>()[0], DbType.Int32, ParameterDirection.Input);
}
网站用户可以输入搜索条件查询订单。用户、状态、状态、OrderID 等
网站与 API 通信。查询参数在 header 中,因此我假设它们以字符串形式出现。 API 通过 Dapper 与 Access 通信。
对于某些条件,他们可以发送多个值。所以我想使用 "IN" 子句。
where UserID in (150, 3303, 16547)
Dapper 处理得很好。
connection.Query<int>("select * from table where Id in @Ids", new { Ids = new int[] { 1, 2, 3 } });
这适用于 MS-Access
SELECT top 100 * from Orders where UserID in (150, 30330)
但这只有在值为整数时才有效。 String 和 Strings 在 Access 中都给出 "Data type mismatch in criteria expression"。
SELECT top 100 * from Orders where UserID in ("150", "30330") // two strings
SELECT top 100 * from Orders where UserID in ("150, 30330") // single string
这可能是巧合,但我看到的所有例子都是整数。如果您未指定大小,Access 会在字符串上引发错误。使用 DynamicParameters 可以轻松指定大小。
但是当字段是一个 int 时,我的 dapper 代码给出了同样的错误(条件表达式中的数据类型不匹配):
var paramlist = new DynamicParameters();
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
paramlist.Add("userId", userId, DbType.String, ParameterDirection.Input, 50);
sbWhere.AppendFormat("AND CustFID in (?) ", paramIndex++);
}
所以我假设问题是我告诉它参数是一个字符串。
但是,如果我将参数设置为 int,则它不会采用具有多个值的字符串。相反,如果我在字符串中包含 (),它会抱怨 'in' 子句中缺少 parens。
我尝试将数字字符串拆分为数组 and/or 列表。
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
var userIds = userId.Split(','); //.ToList(); fails, can't map to native type
paramlist.Add("userId", userIds, DbType.String, ParameterDirection.Input, 1000);
if (userIds.Length > 1) {
sbWhere.AppendFormat("AND CustFID in @userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = @userId ", paramIndex++);
}
}
并给出“:不存在从 object 类型 System.String[] 到已知托管提供程序本机类型的映射。”我说的参数是int32还是string.
更新:
可能有多个搜索条件,所以我使用 DynamicParameters。
这是我尝试实现 Palle Due 的想法。
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
// var userIds = userId.Split(',').Select(i => Int32.Parse(i)).ToList();// fails, can't map to native type
IEnumerable<int> userIds = userId.Split(',').Select<string, int>(int.Parse);
paramlist.Add("userId", userIds, DbType.Int32, ParameterDirection.Input);
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in @userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = @userId ", paramIndex++);
}
}
using (IDbConnection conn = Connection) {
string sQuery = string.Format("SELECT {0} FROM vwweb_Orders {1}", columns, where);
conn.Open();
var result = await conn.QueryAsync<Order>(sQuery, paramlist);
return result.ToList();
}
投掷
Message: System.AggregateException : One or more errors occurred. (Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.)
----> System.InvalidCastException : Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.
----> System.InvalidCastException : Object must implement IConvertible.
@Dai 链接到的 github 页面指定 Dapper 列表支持仅适用于 IEnumerable<int>
。
但据我了解,您的 UserID
是一个整数,所以我不明白您为什么要输入字符串。您需要获取用户输入的字符串并将其转换为IEnumerable<int>
。做这样的事情:
IEnumerable<int> userIDs = (userId?? "").Split(',').Select<string, int>(int.Parse);
var result = connection.Query<int>("SELECT TOP 100 * FROM Orders WHERE UserID IN @Ids", new { Ids = userIDs });
您可能想对其应用一些输入检查,并且您可能还想重新考虑使用 Access 作为网站的 "database"。这不是它的本意。
我放弃了。 Dapper 应该能够处理这个问题,但这是一个较新的功能,所以...
我刚刚自己构建了 IN 子句。
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in ( ");
int paramCnt = 0;
foreach (int id in userIds) {
sbWhere.AppendFormat("?, "); // Access doesn't mind a trailing ,
paramlist.Add("userId" + paramCnt.ToString(), id, DbType.Int32, ParameterDirection.Input);
paramCnt++;
}
sbWhere.AppendFormat(") ");
} else {
sbWhere.AppendFormat("AND CustFID = ? ");
paramlist.Add("userId", userIds.ToArray<int>()[0], DbType.Int32, ParameterDirection.Input);
}