c# - SQL Server 连接在数百次循环后冻结
问题描述
在 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# 对代码进行任何提示,因此非常感谢。
解决方案
考虑返回一个命名的 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 })
{
}
}
推荐阅读
- java - Apache-poi:自动设置合并单元格的大小并使字体加粗
- reflection - 使用反射获取模块的所有 let 绑定
- javascript - 你能给出链接数值并将几个加在一起吗
- javascript - 为什么当我删除搜索字段中的输入过快时结果不会消失?(Javascript)
- python - 如何使用 pandas 水平堆叠基于试验的数据
- python - Pandas - 使用 .apply() 根据条件更新行中的值
- r - R Shiny:出现错误“没有循环中断/下一个,跳转到顶层”
- javascript - 根据文本中的后退箭头符号拆分文本
- javascript - 如何在使用 onFocus 事件打开菜单后取消对按钮的关注
- vhdl - 尝试使用多个组件,形成一个组合循环