SQL Server实例在登录协商期间返回了无效或不受支持的协议版本

时间:2017-07-31 09:41:12

标签: sql-server .net-core

我正在使用dotnetcore 1.1并尝试连接到SQL Server版本8.00.2055

我在项目中有2个连接:一个连接到SqlServer 2016,另一个连接到Sql Server 8.00.2055(Sql Server 2000?)

无法建立第二个连接。这是我得到的错误:

  

2017-07-31T11:34:24.8747442 + 02:00 0HL6NUT8S82KF [错误]用户: - 在登录协商期间,SQL Server实例返回了无效或不支持的协议版本。 (637b11d7)

我使用的连接字符串是Server=MyServerHost; Initial Catalog=MyDatabaseName; User id=sa; Password=********;

知道如何修复此错误吗?

2 个答案:

答案 0 :(得分:8)

.NET Core不支持低于SQL Server 2005的SQL Server版本。或者说,它不支持低于TDS 7.2(SQL Server 2005引入的版本)的TDS协议版本。 source的相关位:

a.tdsVersion = (UInt32)((((((b[0] << 8) | b[1]) << 8) | b[2]) << 8) | b[3]); // bytes are in motorola order (high byte first)
UInt32 majorMinor = a.tdsVersion & 0xff00ffff;
UInt32 increment = (a.tdsVersion >> 16) & 0xff;

// Server responds:
// 0x07000000 -> Sphinx         // Notice server response format is different for bwd compat
// 0x07010000 -> Shiloh RTM     // Notice server response format is different for bwd compat
// 0x71000001 -> Shiloh SP1
// 0x72xx0002 -> Yukon RTM
// information provided by S. Ashwin

switch (majorMinor)
{
    case TdsEnums.YUKON_MAJOR << 24 | TdsEnums.YUKON_RTM_MINOR:     // Yukon
        if (increment != TdsEnums.YUKON_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isYukon = true;
        break;
    case TdsEnums.KATMAI_MAJOR << 24 | TdsEnums.KATMAI_MINOR:
        if (increment != TdsEnums.KATMAI_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isKatmai = true;
        break;
    case TdsEnums.DENALI_MAJOR << 24 | TdsEnums.DENALI_MINOR:
        if (increment != TdsEnums.DENALI_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isDenali = true;
        break;
    default:
        throw SQL.InvalidTDSVersion();
}

供参考:Sphinx是7.0,Shiloh是2000,Yukon是2005,Katmai是2008,Denali是2012(这些是代码名称)。这些名称具有误导性,因为此处验证的版本是TDS协议版本,而不是SQL Server版本。 SQL Server 2012,2014和2016都使用TDS 7.4(每this reference),这就是Denali之外没有检查的原因。

这是来自.NET Framework的reference source的相同代码:

a.tdsVersion = (UInt32)((((((b[0]<<8)|b[1])<<8)|b[2])<<8)|b[3]); // bytes are in motorola order (high byte first)
UInt32 majorMinor = a.tdsVersion & 0xff00ffff;
UInt32 increment  = (a.tdsVersion >> 16) & 0xff;

// Server responds:
// 0x07000000 -> Sphinx         // Notice server response format is different for bwd compat
// 0x07010000 -> Shiloh RTM     // Notice server response format is different for bwd compat
// 0x71000001 -> Shiloh SP1
// 0x72xx0002 -> Yukon RTM
// information provided by S. Ashwin

switch (majorMinor) {
    case TdsEnums.SPHINXORSHILOH_MAJOR<<24|TdsEnums.DEFAULT_MINOR:    // Sphinx & Shiloh RTM
        // note that sphinx and shiloh_rtm can only be distinguished by the increment
        switch (increment) {
            case TdsEnums.SHILOH_INCREMENT:
                _isShiloh = true;
                break;
            case TdsEnums.SPHINX_INCREMENT:
                // no flag will be set
                break;
            default:
                throw SQL.InvalidTDSVersion();
        }
        break;
    case TdsEnums.SHILOHSP1_MAJOR<<24|TdsEnums.SHILOHSP1_MINOR: // Shiloh SP1
        if (increment != TdsEnums.SHILOHSP1_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isShilohSP1 = true;
        break;
    case TdsEnums.YUKON_MAJOR<<24|TdsEnums.YUKON_RTM_MINOR:     // Yukon
        if (increment != TdsEnums.YUKON_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isYukon = true;
        break;
    case TdsEnums.KATMAI_MAJOR<<24|TdsEnums.KATMAI_MINOR:
        if (increment != TdsEnums.KATMAI_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isKatmai = true;
        break;
    case TdsEnums.DENALI_MAJOR << 24|TdsEnums.DENALI_MINOR:
        if (increment != TdsEnums.DENALI_INCREMENT) { throw SQL.InvalidTDSVersion(); }
        _isDenali = true;
        break;
    default:
        throw SQL.InvalidTDSVersion();
}

对TDS 7.0和7.1的支持清晰可见。

我无法在网上找到关于不支持.NET Core中SQL Server 2005以外的任何内容的信息,并且最早的提交(从2015年9月起)已经缺乏支持。鉴于SQL Server 2000自2013年以来一直没有得到扩展支持,这并非不合理。

简而言之:要么坚持使用完整的.NET Framework(尚未放弃对SQL Server 2000的支持),要么升级服务器(非常可取)。可以想象,您也可以将代码分叉以向SQL Core支持SQL Server 2000支持,但这几乎肯定不值得付出努力。

答案 1 :(得分:0)

这是一个旧答案,它最初用于dotnetcore 1.1,但现在随dotnetcore 2.2一起发布,支持OdbcConnection,这将使您可以使用任何旧的Odbc驱动程序。这样,现在您可以连接到SQL Server 2000数据库:

            using (var conn =
                new OdbcConnection("Driver={SQL Server};Server=<YOUR_SERVER>;Database=<YOUR_DB>;Trusted_Connection=True;"))
            {
                conn.Open();
                var cmd = new OdbcCommand("SELECT * FROM SOMETABLE", conn);
                var reader = cmd.ExecuteReader();
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        var values = new Object[reader.FieldCount];
                        var fieldCount = reader.GetValues(values);

                        Console.WriteLine("Found {0} columns.",
                            fieldCount);
                        for (int i = 0; i < fieldCount; i++)
                            Console.WriteLine(values[i]);

                        Console.WriteLine();
                    }
                }
            }

还有其他一些驱动程序也可以使用,而不仅仅是{SQL Server}。检出:https://www.connectionstrings.com/sql-server-2000/以获得其他ODBC连接字符串(需要向下滚动到ODBC部分)。