[英]Why does only the last item of comma-delimited list get processed by stored proc when called from C# web form?
我在Visual Studio 2013和SQL Server 2012中使用C#。
当我的ASP.NET Web表单用户输入以换行符分隔的代码列表并单击“提交”时,后面的代码应读取值,将它们连接成一个逗号分隔的字符串,并将该字符串传递给调用存储方法的方法。 proc。 存储的proc解析出这些值,并在具有匹配代码的每条记录上将active字段设置为1。
产品表定义为:
id (PK, int, not null),
name (varchar(20), not null),
code (varchar(20), null),
active (bit, not null)
产品表包含以下五个记录:
id name code active
-- ---- ---- ------
1 Product 1 AAA 0
2 Product 2 BBB 0
3 Product 3 CCC 0
4 Product 4 DDD 0
5 Product 5 EEE 0
我创建了以下存储过程:
CREATE PROCEDURE [dbo].[MarkListAsActive]
@codeList varchar(MAX)
AS
UPDATE
dbo.Product
SET
active = 1
WHERE
code IN (SELECT val FROM dbo.f_split(@codeList, ','))
dbo.f_split
处理解析以逗号分隔的字符串。 我从这篇文章中复制了它: https : //stackoverflow.com/a/17481595/2677169
如果我在SQL Server Management Studio中执行存储的proc,则所有五个记录都会更新(按预期方式)。
DECLARE @return_value int
EXEC @return_value = [dbo].[MarkListAsActive]
@codeList = N'AAA,BBB,CCC,DDD,EEE'
SELECT 'Return Value' = @return_value
GO
但是,如果我从.aspx页后面的代码中调用存储的proc,则仅列表中的最后一项被标记为活动状态。
protected void SubmitButton_Click(object sender, EventArgs e)
{
string[] codeArray;
char separator = '\n';
OutputLabel.Text = "";
codeArray = ProductCodeTextBox.Text.Split(separator);
OutputLabel.Text += "The products with the following codes were marked as active:<br />";
string codes = "";
// TODO: Replace with regex that changes newlines to commas
for (int i = 0; i < codeArray.Length; i++)
{
codes += codeArray[i] + ",";
OutputLabel.Text += codeArray[i] + "<br />";
}
codes = codes.Substring(0, codes.Length - 1);
Utilities.Log(codes);
DataAccess.MarkListAsActive(codes);
}
public static void MarkListAsActive(string codeList)
{
try
{
string connectionString = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand("[dbo].[MarkListAsActive]", conn)
{
CommandType = CommandType.StoredProcedure
})
{
conn.Open();
command.Parameters.Add("@codeList", codeList);
command.ExecuteNonQuery();
conn.Close();
}
}
catch (Exception ex)
{
Utilities.Log(String.Format("Error in MarkListAsActive: {0}\n{1}", ex.Message, ex.StackTrace));
}
return;
}
请注意,我验证了传递给MarkListAsActive()
的字符串是正确的。
另一种方法:我尝试遍历codeArray并为每个项目调用MarkListAsActive()
。 即使是这种蛮力(且效率低下)的方法也只会更新数组中的最后一项。
还有一个方法:我也尝试了一个表值参数,但是它也只更新了与输入中最后一项相对应的记录。
预先感谢您的帮助。
您的where子句不正确。 你做不到
... code in (select val ...
您需要将f_split函数的结果加入表中。
例如:
UPDATE p
SET p.active = 1
FROM dbo.Product p inner join dbo.f_split(@codeList, ',') f
WHERE p.code = f.val;
将IN子句更改为(SELECT val FROM dbo.f_split(@codeList,','),其中val不为null)。
如果这样不起作用,请按照下列步骤操作:
(无论如何,您应该知道如何调试类似的东西。)
首先,使用SQL事件探查器查看提交给数据库的内容。 有关如何执行此操作的信息,请参见此处 -它的外观没有外观那么差,而且非常宝贵。 如果不是您期望的那样,那么您的前端就有问题。
其次,如果对数据库的调用看起来不错,则采用在SQL事件探查器中看到的参数,并使用它执行dbo.f_split()来查看是否获得了您认为应该的功能。
最后,将您的UPDATE语句更改为SELECT语句,并按照您在第二步中执行的操作运行它,看看您是否获得了看起来正确的东西。
这些步骤之一将不会返回预期的结果,这将导致您遇到问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.