我正在将 java 应用程序转换为 .NET C#,并且正在从 JDBC 迁移到 SqlClient。我正在测试数据库连接,由于以下两个错误之一(有时是一个,有时是另一个),它失败了:
//Debug info
Loading filename: BREConfig.txt
Loading properties from file: BREConfig.txt
Properties Loaded: 23
Setting Config Values...
Server=tcp:###;Initial Catalog=Wc3Online;User ID=####;Password=####;TrustServerCertificate=True; Encrypt=False;
//Error
Connection Timeout Expired. The timeout period elapsed while attempting to consume the pre-login handshake acknowledgement. This could be because the pre-login handshake failed or the server was unable to respond back in time. The duration spent while attempting to connect to this server was - [Pre-Login] initialization=13952; handshake=1056;
//Debug info
Loading filename: BREConfig.txt
Loading properties from file: BREConfig.txt
Properties Loaded: 23
Setting Config Values...
Server=tcp:####;Initial Catalog=###;User ID=####;Password=###;TrustServerCertificate=True; Encrypt=False;
//Error
A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
我能够使用 SQL Server 身份验证通过 RDC 成功连接到数据库,如下所示:
我有一些使用 SqlClient 连接到此数据库服务器的代码:
SqlConnection testConn = BREDBConnectionUtil.GetConnection();
Console.WriteLine(BREDBConnectionUtil.GetConnectionString());
try
{
testConn.Open();
Console.WriteLine("Databse Server Connected, using " + testConn.Database);
testConn.Close();
Console.ReadLine();
} catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
Console.ReadLine();
}
//connection string values pulled from text file and stored in objects
private static SqlConnection con = new();
private static readonly BREConfiguration config = BRESession.GetConfiguration();
private static readonly Logger logger = new();
//Connect to SQL Server 2014
private static readonly string connectionString = "Server=tcp:" + config.GetDbConnection() + ";Initial Catalog=" + config.GetDbName() + ";User ID=" + config.GetDbUser() + ";Password=" + config.GetDbPassword() + ";TrustServerCertificate=True; Encrypt=False;";
//returns an SqlConnection to connect to SQL Server 2014 database
[MethodImpl(MethodImplOptions.Synchronized)]
public static SqlConnection GetConnection()
{
con.ConnectionString = connectionString;
try {
if (con.ConnectionString.Length == 0)
{
con = new SqlConnection(connectionString);
}
} catch (Exception e) {
//print err
}
return con;
}
连接字符串应如下所示:
//Connect to SQL Server 2014
private static readonly string connectionString = $"Server={config.GetDbConnection()};Initial Catalog={config.GetDbName()};User ID={config.GetDbUser()};Password={config.GetDbPassword()}";
SqlClient 字符串的前面不应有
tcp:
。还,
Encrypt=False
已经是默认值,如果您不进行加密(为什么不加密?),则不需要信任服务器证书。
了解连接的另一件重要事情是 C# ADO.Net 作为提供程序的一部分为您提供连接池。这意味着您不应尝试在应用程序中创建和重复使用一个连接对象。相反,为大多数查询创建并及时处置新的连接对象确实更好(好多了)......理想情况下作为
using
块的一部分。
考虑到这一点,
GetConnection()
方法应该看起来更像这样:
public static SqlConnection GetConnection()
{
return new SqlConnection(connectionString);
}
无需想太多,每次给自己一个新对象也意味着你不必再担心同步问题。