如何通过SqlClient / SqlConnection正确连接SQL Server 2014数据库?

问题描述 投票:0回答:2

我正在将 Java 应用程序转换为 .NET 和 C#,并且正在从 JDBC 转向

SqlClient
。我正在测试数据库连接,但由于下面显示的 2 个错误之一而失败(有时是一个错误,有时是另一个错误):

//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;

错误

连接超时已过期。尝试使用登录前握手确认时超时时间已过。这可能是因为登录前握手失败或服务器无法及时响应。尝试连接到该服务器所花费的持续时间为 - [登录前]初始化=13952;握手=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;

错误

与服务器成功建立连接,但在登录前握手期间发生错误。 (提供程序:TCP 提供程序,错误:0 - 现有连接被远程主机强制关闭。)

我能够使用 SQL Server 身份验证通过 RDC 成功连接到数据库,如下所示:

SQL Server connection ui

object connection here

我有一些使用

SqlClient
连接到此数据库服务器的代码:

SqlConnection testConn = BREDBConnectionUtil.GetConnection();
Console.WriteLine(BREDBConnectionUtil.GetConnectionString());  

try
{
    testConn.Open();
    Console.WriteLine("Database 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 a 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;
}
c# .net sql-server ado.net sqlclient
2个回答
1
投票

连接字符串应如下所示:

//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 API 作为提供程序的一部分为您提供连接池。这意味着您不应尝试在应用程序中创建和重复使用一个连接对象。相反,为大多数查询创建并立即处置新的连接对象确实更好(更好得多)......理想情况下作为

using
块的一部分。

考虑到这一点,

GetConnection()
方法应该看起来更像这样:

public static SqlConnection GetConnection()
{
    return new SqlConnection(connectionString);
}

没必要想太多。无论如何,您通常已经拥有处理异常的更高级别的代码,并且每次给自己一个新对象也意味着您不必再担心同步。


然后我们可以像这样测试连接:

Console.WriteLine(BREDBConnectionUtil.GetConnectionString());  
using var testConn = BREDBConnectionUtil.GetConnection();
            
try
{
    testConn.Open();
    Console.WriteLine($"Databse Server Connected, using {testConn.Database}");
    // no need to call .Close(). 
    // The using directive takes care of it automatically **and more safely**
    // at the end of the scope block
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    Console.WriteLine(ex.StackTrace);
}
// but if you DO want to call .Close() manually, or not have a using directive, 
// it should be HERE, as part of a finally block
// (hint: this was true in Java, too)
Console.ReadLine();

但再次强调:这只是一个测试。由于我们为每个查询创建一个新的连接对象,因此预先测试或打开连接没有太多意义。


0
投票

这个问题似乎与安全协议不兼容。我们的 SQL Server 使用 TLS 1.2,而我尝试连接的笔记本电脑使用 TLS 1.3。

我的猜测是 TCP 握手成功,而 TLS 握手失败,SQL Server 被归咎于它导致 TCP 错误,

(provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)

不过需要进一步测试才能确定。

© www.soinside.com 2019 - 2024. All rights reserved.