繁体   English   中英

从C#Web表单调用时,为什么只有逗号分隔列表的最后一项才由存储的proc处理?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM