【问题标题】:Run Stored Procedure and Check Value Exists or Not C#运行存储过程并检查值是否存在 C#
【发布时间】:2020-11-21 09:05:54
【问题描述】:

我有这个存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE ClientDelete
    @clientid uniqueidentifier
AS
BEGIN
    SET NOCOUNT ON;
    
    UPDATE Clients SET enabled=1,editDate=GETUTCDATE() WHERE clientid=@clientid
END

使用此功能文件:


     Feature: ClientDelete

Scenario: Client Delete
    Given a clean database
    Given the following Clients table
    | clientid | name    | url          | enabled | lastChangedBy | createDate | editDate   |
    | 1        | Client1 | https://test | true    | test          | 2000-01-01 | 2000-01-01 |
    | 2        | Client2 | https://test | true    | test          | 2000-01-01 | 2000-01-01 |
    When the "ClientDelete" stored procedure is run with the following parameters
    | name     | value |
    | clientid | 11    |
    Then the following is returned
    | clientid | name    | url          | enabled | lastChangedBy | createDate | editDate   |
    | 1        | Client1 | https://test | false   | test          | 2000-01-01 | 2000-01-01 |
    | 2        | Client2 | https://test | true    | test          | 2000-01-01 | 2000-01-01 |

C#代码:


 [When(@"the ""(.*)"" stored procedure is run with the following parameters")]
        public void WhenTheStoredProcedureIsRunWithTheFollowingParameters(string procName, Table table)
        {
            using (var con = CreateDBConnection())
            {
                using (var cmd = con.CreateCommand())
                {
                    cmd.CommandText = procName;
                    cmd.CommandType = CommandType.StoredProcedure;

                    foreach (var row in table.Rows)
                    {
                        var param = cmd.CreateParameter();
                        param.ParameterName = row.Values.First();

                        if (param.ParameterName == "clientids")
                        {
                            param.SqlDbType = SqlDbType.Structured;
                            param.Value = new List<SqlDataRecord>()
                            {
                                ToSqlDataRecord(new Guid(row.Values.Last()))
                            };
                        }
                        else if (param.ParameterName == "docTypes")
                        {
                            param.SqlDbType = SqlDbType.Structured;
                            if (row.Values.Last() != "NULL")
                            {
                                param.Value = new List<SqlDataRecord>()
                                {
                                    ToSqlDataRecord(row.Values.Last())
                                };
                            }
                        }
                        else if (row.Values.Last() != "NULL")
                            param.Value = row.Values.Last();
                        else
                            param.Value = DBNull.Value;

                        cmd.Parameters.Add(param);
                    }

                    var results = new DataTable();
                    using (var adapter = new SqlDataAdapter((SqlCommand)cmd))
                    {
                        adapter.Fill(results);
                    }

                    _context.Add("Results", results);
                }
            }
        }
   [Then(@"the following is returned")]
        public void ThenTheFollowingIsReturned(Table table)
        {
            var results = _context.Get<DataTable>("Results");
            Assert.AreEqual(table.Rows.Count, results.Rows.Count);

            for (int i = 0; i < results.Rows.Count; i++)
            {
                var expectedRow = table.Rows[i];
                var actualRow = results.Rows[i];

                for (int j = 0; j < table.Header.Count; j++)
                {
                    var name = table.Header.ElementAt(j);
                    var type = actualRow[name].GetType();
                    object expectedValue = expectedRow[name];
                    if (expectedValue.ToString().IsNullText())
                        expectedValue = null;
                    else if (type != typeof(DBNull))
                        expectedValue = TypeDescriptor.GetConverter(type).ConvertFromInvariantString(expectedRow[name]);
                    var actualValue = Convert.IsDBNull(actualRow[name]) ? null : actualRow[name];
                    Assert.AreEqual(expectedValue, actualValue, name);
                }
            }
        }

@Then 不起作用,因为它没有从存储过程中返回任何内容,所以我想检查值是否已更新或是否存在。 我也有这个,然后用于返回行数据并且工作正常的多个存储过程,但不适用于添加、删除、更新。

注意:我需要在存储过程中不添加输出参数。

【问题讨论】:

    标签: c# sql stored-procedures specflow gherkin


    【解决方案1】:

    在你的存储过程中更新后添加:

    SELECT @@ROWCOUNT AS Result
    

    这将返回受上一个更新语句影响的行数。然后,如果结果 > 0,您可以签入您的 C# 代码。

    @@ROWCOUNT 文档: https://docs.microsoft.com/en-us/sql/t-sql/functions/rowcount-transact-sql?view=sql-server-ver15

    【讨论】:

    • 感谢您的建议,它现在返回 1 但在 var type = actualRow[name].GetType(); 失败抱怨列clientid不属于表
    • 我认为由于迭代它再次寻找相同的列名??
    【解决方案2】:

    您需要在Then 步骤中再次查询客户表。 DeleteClient 存储过程不返回任何内容,也不填充输出变量。您唯一的办法是在Then the following is returned 中再次查询客户表。您可以使用 Table 扩展方法 CompareToSet(...) 而不是自己手动进行断言。

    【讨论】:

    • 我现在只在 GETUTCDATE() 函数返回当前日期和时间时失败,但我无法在功能文件中传递时间。这个时间怎么验证?
    • 目前我也在使用表名,但对于许多删除或更新存储过程,我想使用相同的方法,而不是为每个方法创建 1,这确实是一个更大的数字。你建议表名作为变量还是别的什么?
    • @Techie:最好用普通的旧 C# 编写这些测试。
    • 我们可以检查gherkin文件中的GETUTCDATE()函数吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 2011-08-08
    • 2012-10-01
    • 1970-01-01
    相关资源
    最近更新 更多