【问题标题】:SQL Server connection freezes after a few hundred loopsSQL Server 连接在数百次循环后冻结
【发布时间】:2021-10-24 10:53:24
【问题描述】:

在 C#.NET Core 5 项目中,我使用 System.Data.SQLClient 4.8.2 连接到 SQL Server 11。

这段代码运行良好。

    public List<Contract> ReadDBView(Contract contract)
    {
        List<Contract> contracts = new List<Contract> { };
        try
        {
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

            builder.DataSource = "server01";
            builder.UserID = "user1";
            builder.Password = "SecretPassword";
            builder.InitialCatalog = "archiv1";
            String sql = "SELECT name, group_name, group_country_code, FROM[dbo].[GROUPS] where number like '%" + contract.Number.ToString() + "'";

            using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
            {
                connection.Open();
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            contract.DealerName = reader["name"].ToString();
                            contract.GroupName = reader["group_name"].ToString();
                            contract.Country = reader["group_country_code"].ToString();
                            contracts.Add(contract);
                        }
                    }
                }
                connection.Close();
            }
        }
        catch (SqlException e)
        {
            Console.WriteLine(e.ToString());
        }

        return contracts;
    }

但过了一会儿它就冻结了——知道如何防止冻结吗?

返回值有时为空。由于我很长时间没有使用 C# 做任何代码提示,非常感谢。

【问题讨论】:

  • 我强烈建议您修复代码中的主要安全漏洞; SQL 注入现在应该已经死了。我们更喜欢参数是有原因的。
  • 你多久运行一次?你有针对同一张表的任何其他 SQL 语句吗?
  • @Larnu 你能分享一个好例子的链接吗
  • 知道SQL Injection很重要。
  • @jgauffin 我会检查,但可能不超过 5000 次

标签: c# sql-server .net-core


【解决方案1】:

考虑返回一个命名的 ValueTuple

以下示例使用了一个与您的表不匹配的现有表,但演示了一种确定是否有异常抛出的方法。使用 Console.WriteLine 可以进行调试(最好使用 Debug.WriteLine),但为什么不设置用于生产。

  • 考虑按照@jeroen Mostert 的建议添加日志记录
  • 对于类似的情况,表没有设置索引,因此效率不高。关键是要弄清楚是否抛出了异常。
  • 使用 C#9,.NET Core 5 语法,例如using 声明而不是声明正文。

后端代码

public class SqlOperations
{
    public static string ConnectionString =
        "Data Source=.\\SQLEXPRESS;Initial Catalog=PaginationExample;Integrated Security=True";


    public static (List<Contract>, Exception exception) ReadDBView(string firstNameValue)
    {
        List<Contract> contracts = new();

        var selectStatement = 
            "SELECT Id, FirstName, LastName, Balance " + 
            "FROM dbo.LotsOfData " + 
            "WHERE FirstName LIKE @FirstNameLike;";

        try
        {
            using var cn = new SqlConnection() { ConnectionString = ConnectionString };
            using var cmd = new SqlCommand() { Connection = cn, CommandText = selectStatement };

            cmd.Parameters.Add("@FirstNameLike", SqlDbType.NVarChar).Value = firstNameValue;
            
            cn.Open();

            var reader = cmd.ExecuteReader();

            if (!reader.HasRows) return (contracts, null);
            while (reader.Read())
            {
                contracts.Add(new Contract()
                {
                    Id = reader.GetInt32(0),
                    FirstName = reader.GetString(1),
                    LastName = reader.GetString(2),
                        
                    Balance = reader.IsDBNull("Balance") ? 
                        (decimal?)null : 
                        reader.GetDecimal("Balance")
                            
                });
            }

            return (contracts, null);

        }
        catch (Exception exception)
        {
            return (null, exception);
        }

        
    }
}

// place in own file
public class Contract
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public decimal? Balance { get; set; }

    public override string ToString() => $"{FirstName} {LastName}";

}

使用单元测试方法

[TestMethod]
public void LargeLike()
{
    var (contracts, exception) = SqlOperations.ReadDBView("%nia");

    if (contracts.Count > 0 && exception is null)
    {
        Debug.WriteLine(contracts.Count);
    }
    else
    {
        Debug.WriteLine(exception is not null ? exception.Message : "No matches");
    }
}

using 的语法

public static void UsingExample()
{
    // C#9, .NET Core 5 syntax
    using var cn1 = new SqlConnection() { ConnectionString = ConnectionString };

    // .NET 4.8 syntax
    using (var cn2 = new SqlConnection() { ConnectionString = ConnectionString })
    {
        
    }
    
}

【讨论】:

猜你喜欢
  • 2013-12-21
  • 2017-10-20
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多