為什么要使用ODBC連接SQL Server?
ODBC是什么?
ODBC是什么?我也不知道,用摘抄一個(gè)互聯(lián)網(wǎng)上的話來(lái)解釋?zhuān)篛DBC英文全稱(chēng)為:Open Database Connectivity。用于在不同的操作系統(tǒng)和數(shù)據(jù)庫(kù)管理系統(tǒng)之間進(jìn)行數(shù)據(jù)訪問(wèn)的標(biāo)準(zhǔn)化接口。它提供了一組函數(shù)和API,使得應(yīng)用程序可以通過(guò)統(tǒng)一的方式訪問(wèn)不同類(lèi)型的數(shù)據(jù)源。大多數(shù)數(shù)據(jù)源都有適用的 ODBC 驅(qū)動(dòng)程序。
那么ODBC和ADO.NET以及JDBC的關(guān)系是什么?讓GPT來(lái)回答一下吧:
ODBC(Open Database Connectivity)和ADO.NET(ActiveX Data Objects .NET)是 Microsoft 開(kāi)發(fā)的數(shù)據(jù)庫(kù)訪問(wèn)接口。而 JDBC(Java Database Connectivity)則是由 Sun Microsystems 開(kāi)發(fā)的 Java 數(shù)據(jù)庫(kù)訪問(wèn)標(biāo)準(zhǔn)。
ODBC 和 JDBC 都提供了一種通用的方式來(lái)訪問(wèn)數(shù)據(jù)庫(kù),允許開(kāi)發(fā)人員使用標(biāo)準(zhǔn) SQL 語(yǔ)句來(lái)操作各種不同類(lèi)型的數(shù)據(jù)庫(kù)。ADO.NET則是微軟針對(duì) .NET 平臺(tái)開(kāi)發(fā)的數(shù)據(jù)庫(kù)訪問(wèn)接口,提供了與 ODBC 類(lèi)似的功能,但更加面向?qū)ο?,具有更好的性能和可擴(kuò)展性。
為什么要使用ODBC而不使用EFCore?
我也想使用EFCore或者其他的ORM框架,但是走不通!首先場(chǎng)景是這樣子的,我們業(yè)務(wù)中有一個(gè)地方需要去連接甲方的數(shù)據(jù)庫(kù),然后查詢(xún)數(shù)據(jù),這個(gè)時(shí)候我們是使用的System.Data.SqlClient+Dapper來(lái)執(zhí)行SQL查詢(xún)的,可是一直報(bào)錯(cuò),大概信息就是類(lèi)似下面這些
// 因?yàn)樾薷牧撕脦状?,所以信息我已?jīng)對(duì)不上了,大概出現(xiàn)了下面的這些
Connection Timeout Expired. The timeout period elapsed during the post-login phase. The connection could have timed out while waiting for server to complete the login process and respond; Or it could have timed out while attempting to create multiple active connections. The duration spent while attempting to connect to this server was - [Pre-Login] initialization=3; handshake=10; [Login] initialization=0; authentication=0; [Post-Login] complete=14074;
或者
Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake.
(provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)
System.IO.EndOfStreamException: End of stream reached
或者
SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL。遇到這個(gè)問(wèn)題,我們首先想在連接字符串上操作去修復(fù)解決這個(gè)問(wèn)題,但是最后沒(méi)有解決,我們想在公司復(fù)現(xiàn),首先直接在我自己電腦本地連接sqlserver2019是沒(méi)有問(wèn)題的,然后沒(méi)辦法又在服務(wù)器安裝了sqlserver2008也沒(méi)有問(wèn)題(這里我還傻不拉幾想著使用容器部署一個(gè)sqlserver2008快,然后信了一個(gè)博客老哥的鬼話去拉取他的鏡像,結(jié)果拉取下來(lái)是2019版本的,后來(lái)查閱資料才知道sqlserver2008哪里有什么鏡像),然后又模擬正式環(huán)境容器化部署,然后終于復(fù)現(xiàn)了上面的錯(cuò)誤,然后就開(kāi)始嘗試,我們也在網(wǎng)絡(luò)上查閱了資料,終于在一個(gè)文章上看到sqlserver2008不支持TLS1.2,然后按照那個(gè)文檔的方法去降低容器TSL版本,比如dockerfile增加
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf結(jié)果還是不行,錯(cuò)誤變了,繼續(xù)查閱文章,然后終于找到【嘿dotNet】公眾號(hào)老哥的一個(gè)博客,他在2019年遇到了這個(gè)問(wèn)題,我將他總結(jié)性的那部分摘抄出來(lái)
.net core 的System.Data.SqlClient支持的最低SqlServer版本是2008 r2 SP3,小于這個(gè)版本的就會(huì)報(bào)這個(gè)錯(cuò)。
來(lái)源:https://github.com/dotnet/corefx/issues/9719
結(jié)論:.netcore 連接使用sqlserver遇到以上報(bào)錯(cuò)1、報(bào)錯(cuò)2的同學(xué),需注意:**.net core 的System.Data.SqlClient支持的最低SqlServer版本是2008 r2 SP3**請(qǐng)先檢查數(shù)據(jù)庫(kù)版本。
呼~(yú)這個(gè)鬼問(wèn)題浪費(fèi)了我整整兩天+(3個(gè)熬夜)
文章地址:https://www.cnblogs.com/xiaxiaolu/p/10309064.html
雖然這個(gè)文章的評(píng)論中也提到了升級(jí)數(shù)據(jù)庫(kù)版本可以解決,但是?甲方那邊升級(jí)數(shù)據(jù)庫(kù)肯定不現(xiàn)實(shí)的,那只好考慮換個(gè)組件什么的?我也嘗試了EFCore依賴(lài)的包Microsoft.Data.SqlClient也是不行,所以這個(gè)時(shí)候就咨詢(xún)其他部門(mén)(java)那邊連接正常不?他們回復(fù)沒(méi)有問(wèn)題,然后就產(chǎn)生了要不再搞個(gè)java服務(wù)去連接的念頭???這多尷尬,連接微軟家的數(shù)據(jù)庫(kù)還需要去麻煩其他語(yǔ)言???
領(lǐng)導(dǎo)說(shuō)再找找資料 。。。然后就找到了Microsoft ODBC Driver for SQL Server
開(kāi)始操作
在Nuget上搜索odbc,排名第一個(gè)的一個(gè)包是微軟和dotnetframework維護(hù)的,最近一次更新在幾天前,還是8.0.0版本怪新,那就根據(jù)文檔去操作吧,這里需要注意的是使用ODBC去操作數(shù)據(jù)庫(kù)是需要手動(dòng)安裝驅(qū)動(dòng)的,比如我本地調(diào)試需要去下載驅(qū)動(dòng)安裝
下面來(lái)演示一個(gè)連接的小示例,新建一個(gè)控制臺(tái)項(xiàng)目名字叫做MsSqlNetCoreOdbc(這里我直接創(chuàng)建.Net6的控制臺(tái)項(xiàng)目),然后安裝nuget包
<ItemGroup>
<PackageReference Include="System.Data.Odbc" Version="6.0.1" />
</ItemGroup>編寫(xiě)如下代碼
using System.Data.Odbc;
try
{
var str = "Server=xxxx;Database=dbName;Uid=sa;Pwd=123xxxx;Encrypt=no;driver=ODBC Driver 18 for SQL Server";
await using var connection = new OdbcConnection(str);
connection.Open();
string sqlQuery = "Select @@version";
var command = new OdbcCommand(sqlQuery, connection);
var reader = command.ExecuteScalar();
Console.WriteLine(reader.ToString());
Console.WriteLine("conn success");
Console.WriteLine("over");
}
catch (Exception ex)
{
Console.WriteLine($"message:{ex.Message} stackTrace:{ex.StackTrace}");
}
Console.ReadLine();這里光看這個(gè)示例的話,和之前使用System.Data.SqlClient的改動(dòng)確實(shí)不大,換了一個(gè)包,使用OdbcConnection創(chuàng)建DbConnection(需要注意的是如果你要使用到參數(shù)化等就需要注意了,它的參數(shù)化不是@key,而是?key? 我??)
這里在安裝好驅(qū)動(dòng)的情況下直接運(yùn)行代碼啟動(dòng)調(diào)試,會(huì)輸出下面的信息
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
Apr 2 2010 15:48:46
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: ) (Hypervisor)
conn success
over然后就要容器化部署測(cè)試是否可行了,那么按照官網(wǎng)的文章以及互聯(lián)網(wǎng)上的資料去拼湊嘗試給容器安裝驅(qū)動(dòng),官網(wǎng)文章地址在最下面 ,比如看他Ubuntu的示例
if ! [[ "18.04 20.04 22.04 23.04" == *"$(lsb_release -rs)"* ]];
then
echo "Ubuntu $(lsb_release -rs) is not currently supported.";
exit;
fi
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
# optional: for bcp and sqlcmd
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc
# optional: for unixODBC development headers
sudo apt-get install -y unixodbc-dev嘗試去容器化部署吧,選中控制臺(tái)項(xiàng)目右鍵添加dockerfile文件,并且做下面的修改
? 降低容器tls版本
? 安裝odbc操作驅(qū)動(dòng)
最后dockerfile需要增加以下內(nèi)容
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && apt-get update && \
apt-get install -y unixodbc unixodbc-dev curl
RUN curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc && curl https://packages.microsoft.com/config/debian/11/prod.list > /etc/apt/sources.list.d/mssql-release.list && \
apt-get update && \
ACCEPT_EULA=Y apt-get install -y msodbcsql18 && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*
COPY ./MSSQL_NetCore_Odbc/odbcinst.ini /etc/odbcinst.ini
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /etc/ssl/openssl.cnf
RUN sed -i 's/MinProtocol = TLSv1.2/MinProtocol = TLSv1/g' /usr/lib/ssl/openssl.cnf其中odbcinst.ini內(nèi)容為
[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver=/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.3.so.2.1
UsageCount=1然后重新啟動(dòng)生成容器,發(fā)現(xiàn)已經(jīng)連接成功,輸出信息如下
圖片
連接成功,結(jié)束
參考資料
Microsoft ODBC Driver for SQL Server:https://learn.microsoft.com/zh-cn/sql/connect/odbc/microsoft-odbc-driver-for-sql-server?view=sql-server-ver16
SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL:https://www.cnblogs.com/printertool/p/14084385.html
https://www.cnblogs.com/yuanzhongkui/p/4022557.html 連接sqlsever
Connection open error . Connection Timeout Expired. The timeout period elapsed during the post-login phase.
驅(qū)動(dòng)下載地址:https://learn.microsoft.com/zh-cn/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver16


























