今天有群友在群里問 C#
能不能在 Linux
下訪問 Access數(shù)據(jù)庫
?
我覺得這很有趣,因此研究折騰了一下,也因?yàn)楹芫脹]有寫博文了,所以特意上來寫博文分享經(jīng)驗(yàn)。
運(yùn)行環(huán)境
- 操作系統(tǒng):
Ubuntu 22.04.3 LTS (Jammy)
- 開發(fā)工具:
Visual Studio 2022 (17.8.0)
- 運(yùn)行時(shí)版本:
.NET Runtime 8.0
- 依賴庫:
unixodbc
、mdbtools
、odbc-mdbtools
依賴庫安裝
apt-get update
sudo apt-get install unixodbc mdbtools odbc-mdbtools
依賴庫版本信息
- apt list --installed | grep odbc
libodbc1/jammy,now 2.3.9-5 amd64 [installed,automatic]
libodbc2/jammy,now 2.3.9-5 amd64 [installed,automatic]
libodbccr2/jammy,now 2.3.9-5 amd64 [installed,automatic]
libodbcinst2/jammy,now 2.3.9-5 amd64 [installed,automatic]
odbc-mdbtools/jammy,now 1.0.0+dfsg-1 amd64 [installed]
odbcinst1debian2/jammy,now 2.3.9-5 amd64 [installed,automatic]
odbcinst/jammy,now 2.3.9-5 amd64 [installed,automatic]
unixodbc-common/jammy,now 2.3.9-5 all [installed,automatic]
unixodbc/jammy,now 2.3.9-5 amd64 [installed]
- apt list --installed | grep mdb
liblmdb0/jammy,now 0.9.24-1build2 amd64 [installed,automatic]
libmdb3/jammy,now 1.0.0+dfsg-1 amd64 [installed,automatic]
libmdbsql3/jammy,now 1.0.0+dfsg-1 amd64 [installed,automatic]
mdbtools/jammy,now 1.0.0+dfsg-1 amd64 [installed]
odbc-mdbtools/jammy,now 1.0.0+dfsg-1 amd64 [installed]
Linux平臺(tái) 下的 ODBC 配置
- /etc/odbc.ini
[access_db] # 隨意命名,會(huì)在項(xiàng)目代碼里用到它
Description=Microsoft Access Database
Driver=MDBW
ServerName = localhost
Database=/root/Database1.mdb # 按你的實(shí)際路徑改寫,要有讀寫權(quán)限
- /etc/odbcinst.ini
[MDBW] # 隨意,在odbc.ini文件用到它
Description=MDBTools Driver Wide # 隨意
Driver=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbcW.so # 按你的實(shí)際路徑改寫
Setup=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbcW.so # 按你的實(shí)際路徑改寫
FileUsage=1
UsageCount=1
[MDBTools]
Description=MDBTools Driver # 隨意
Driver=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so # 按你的實(shí)際路徑改寫
Setup=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so # 按你的實(shí)際路徑改寫
FileUsage=1
UsageCount=1
[ODBC]
Trace=1
TraceFile=/tmp/mdb.log # 有寫入權(quán)限的文件路徑
Demo 項(xiàng)目代碼
- OdbcForLinuxTestApp.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RuntimeIdentifiers>linux-x64;win-x64</RuntimeIdentifiers>
<SelfContained>true</SelfContained>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Data.Odbc" Version="8.0.0" />
<PackageReference Include="System.Data.OleDb" Version="8.0.0" />
</ItemGroup>
</Project>
- Program.cs
using System.Data;
using System.Data.Common;
using System.Data.Odbc;
using System.Data.OleDb;
namespace OdbcForLinuxTestApp;
internal sealed class Program
{
static async Task Main(string[] args)
{
string connectionStrings;
if (OperatingSystem.IsWindows())
{
string mdbFile = Path.Combine(AppContext.BaseDirectory, "Database1.mdb");
connectionStrings = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={mdbFile}";
}
else
{
//root/Database1.mdb
connectionStrings = "DSN=access_db;";
}
await using (DbConnection conn = GetDbConnection(connectionStrings))
{
await conn.OpenAsync();
DbCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select [ID],[UserName] from Users";
DbDataReader reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
//The MDBTools does not support the use of column names
string userName = reader.GetString(1);
Console.WriteLine("UserName: " + userName);
}
}
}
private static string DbProviderName => OperatingSystem.IsWindows() ? "System.Data.OleDb" : "System.Data.Odbc";
private static DbConnection GetDbConnection(string connectionStrings)
{
RegisterOdbcOrOleDbFactory();
DbProviderFactory dbFactory = DbProviderFactories.GetFactory(DbProviderName);
DbConnection? conn = dbFactory.CreateConnection();
if (conn == null)
{
return OperatingSystem.IsWindows() ? new OleDbConnection(connectionStrings) : new OdbcConnection(connectionStrings);
}
conn.ConnectionString = connectionStrings;
return conn;
}
private static int _isRegisteredDbFactory;
private static void RegisterOdbcOrOleDbFactory()
{
if (Interlocked.CompareExchange(ref _isRegisteredDbFactory, 1, 0) == 0)
{
string dbProviderName = DbProviderName;
IEnumerable<string> providerInvariantNames = DbProviderFactories.GetProviderInvariantNames();
string? invariantName = providerInvariantNames.FirstOrDefault(x => x.Equals(dbProviderName, StringComparison.InvariantCultureIgnoreCase));
if (string.IsNullOrWhiteSpace(invariantName))
{
DbProviderFactories.RegisterFactory(dbProviderName, OdbcFactory.Instance);
}
}
}
}
編譯和發(fā)布 Demo 項(xiàng)目代碼
準(zhǔn)備工作
- 創(chuàng)建
OdbcForLinuxTestApp
目錄 - 將上述兩個(gè)代碼文件放入
OdbcForLinuxTestApp
目錄 - 安裝
.NET SDK 8.0.100
編譯和發(fā)布
在 OdbcForLinuxTestApp
目錄下,執(zhí)行命令:
dotnet publish -c Release -f net8.0 -r win-x64 -o ./publish/win-x64 # 如果只考慮 Linux平臺(tái),該命令可忽略
dotnet publish -c Release -f net8.0 -r linux-x64 -o ./publish/linux-x64
運(yùn)行 OdbcForLinuxTestApp
注意:
Database1.mdb
數(shù)據(jù)庫文件需要提前放到正確的路徑,以odbc.ini文件
的Database
配置項(xiàng)為準(zhǔn)。
cd ./publish/linux-x64
chmod +x OdbcForLinuxTestApp # 授予可執(zhí)行權(quán)限
./OdbcForLinuxTestApp
輸出:
UserName: Allen
UserName: Joy
折騰過程中遇到的問題
-
搜了幾個(gè)配置例子,有的說
libmdbodbc.so
在/usr/lib
目錄下,
也有的在/usr/local/lib/odbc
目錄下,而我最終是在/usr/lib/x86_64-linux-gnu/odbc
目錄下找到。文章來源:http://www.zghlxwxcb.cn/news/detail-747146.html -
mdbtools 不支持使用列名訪問,只能用列索引。文章來源地址http://www.zghlxwxcb.cn/news/detail-747146.html
其它
- 參考:https://github.com/mdbtools/mdbtools/issues/347
- MDB Tools:https://mdbtools.github.io
到了這里,關(guān)于在Linux平臺(tái)下使用.NET Core訪問Access數(shù)據(jù)庫讀取mdb文件數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!