我正在尝试从我的简单C#应用程序中尝试捕获插入SQL查询,但是当我尝试将数据插入到具有添加到userIDList参数中的用户ID的数据库时,出现错误说< / p>
传入的请求包含太多参数。服务器支持 最多2100个参数。
userIDList有时会包含60个以上的数组,然后会弹出错误。
我的SQL CommandText将包含
"SELECT * FROM TIME_ATTENDANCE_REPORT WHERE TRXDATETIME = @Date AND USERID IN (001,002,003,004,....)
所以我认为如果超过某个数字,那么错误弹出
以下是我的示例代码:
List<string> userIDList = new List<string>();
using (SqlCommand sqlDBComm = new SqlCommand())
{
openConnection();
SqlDataReader sqlDBReader;
sqlDBReader = null;
sqlDBComm.CommandText = "SELECT * FROM TIME_ATTENDANCE_REPORT WHERE TRXDATETIME = @Date AND USERID IN (" + string.Join(",", userIDList) + ") ORDER BY USERID ASC ";
sqlDBComm.Parameters.Add("@Date", SqlDbType.DateTime);
sqlDBComm.Parameters["@Date"].Value = GetDateFrom;
sqlDBComm.Connection = sqlDB;
sqlDBComm.CommandType = CommandType.Text;
try
{
sqlDBReader = sqlDBComm.ExecuteReader();
t.Load(sqlDBReader);
sqlDBReader.Close();
if (t.Rows.Count > 0)
{
status = "Update";
}
else
{
status = "Insert";
}
}
catch (Exception errMsg)
{
MessageBox.Show("Error Code: " + errMsg.ToString());
}
finally
{
sqlDBReader.Close();
closeConnection();
}
}
任何其他解决方案都可以解决此问题? 感谢
答案 0 :(得分:1)
有很多方法可以解决这个问题。
您可以将单个@IDList参数作为单个逗号分隔的字符串发送,而不是将ID列表作为单独的参数发送,并将其解析为服务器端的ID。这是我用于此的一个函数(从Jeff Moden的代码中借用和修改):
CREATE FUNCTION [dbo].[iSplitter] (@Parameter VARCHAR(MAX))
RETURNS @splitResult TABLE (number INT, [value] INT)
AS
BEGIN
SET @Parameter = ','+@Parameter +',';
WITH cteTally AS
(
SELECT TOP (LEN(@Parameter))
ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N
FROM Master.sys.All_Columns t1
CROSS JOIN Master.sys.All_Columns t2
)
INSERT @splitResult
SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
SUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,N+1)-N-1) AS [Value]
FROM cteTally
WHERE N < LEN(@Parameter) AND SUBSTRING(@Parameter,N,1) = ','
RETURN
END
创建此功能一次后,我会这样做:
sqlDBComm.CommandText = @"SELECT * FROM TIME_ATTENDANCE_REPORT tar
inner Join dbo.iSplitter(@UserIdList) ul on tar.USERID = ul.[value]
WHERE TRXDATETIME = @Date
ORDER BY USERID ASC ";
sqlDBComm.Parameters.AddWithValue("@UserIdList",string.Join(",", userIDList));
这适用于5-6K整数ID,但如果与20-30K或更多ID一起使用则超时。然后我创建了另一个替代方案作为CLR过程,并且在不到一秒的时间内解析列表服务器端。但我认为这个足以满足您的需求。
另一种方法是将ID作为XML参数发送并再次解析服务器端。
另一种方法是发送表参数。
PS:这是link that shows sample code for other ways。该网站使用土耳其语,但C#中的代码非常清晰,按照方法分开。
编辑:使用Northwind Orders表的XML示例:
void Main()
{
int[] IDList = { 10265,10266,10267,10268,10269,10270,10271,10272,10273,10274,10275, 10320, 10400 };
var idsAsXML = new XElement("IDS",
from i in IDList
select new XElement("Row", new XAttribute("Id", i)));
string sql = @"
DECLARE @hDoc int;
DECLARE @tbl TABLE (Id int);
exec sp_xml_preparedocument @hDoc OUTPUT, @XML;
INSERT @tbl
SELECT *
FROM OPENXML(@hDoc, @Nodename, 1) WITH (Id int);
EXEC sp_xml_removedocument @hDoc;
select * from Orders o
where exists (select * from @tbl t where t.Id = o.OrderId) ";
DataTable tbl = new DataTable();
using (SqlConnection con = new SqlConnection(@"server=.\SQLExpress;Trusted_Connection=yes;Database=Northwind"))
{
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("@XML", idsAsXML.ToString());
cmd.Parameters.AddWithValue("@NodeName", "/IDS/Row");
con.Open();
tbl.Load(cmd.ExecuteReader());
con.Close();
}
//tbl.Dump(); // linqPad luxury
}
答案 1 :(得分:1)
您可以创建Table-Valued-Parameter并将其作为参数传递。它要求您在数据库中创建一个新类型,并使您能够将数组传递给查询,并让数据库将其视为表。如果这是你做了很多的事情,它可以派上用场。
我无法再访问我实施此项目的项目,但blog post中提供了所有内容。下面的代码没有经过测试,但我希望它可以帮助您找到正确的方向。
1。在数据库中创建新类型:
CREATE TYPE integer_list_tbltype AS TABLE (n int NOT NULL PRIMARY KEY)
2. 将其作为参数传递:
sqlDBComm.Parameters.Add("@userIds", SqlDbType.Structured)
sqlDBComm.Parameters["@userIds"].Direction = ParameterDirection.Input
sqlDBComm.Parameters["@userIds"].TypeName = "integer_list_tbltype"
sqlDBComm.Parameters["@userIds"].Value = CreateDataTable(userIDList)
3. 创建参数的方法:
private static DataTable CreateDataTable(IEnumerable<int> ids) {
DataTable table = new DataTable();
table.Columns.Add("n", typeof(int));
foreach (int id in ids) {
table.Rows.Add(id);
}
return table;
}
4. 在SQL中使用它:
... AND USERID IN (SELECT n FROM @userIds)
从这里 CreateDataTable
:
How to pass table value parameters to stored procedure from .net code
从这里休息:
http://www.sommarskog.se/arrays-in-sql-2008.html#introduction