|
今天有群友在群里问 C# 能不能在 Linux 下访问 Access数据库?
我觉得这很有趣,因此研究折腾了一下,也因为很久没有写博文了,所以特意上来写博文分享经验。
运行环境
- 操作系统:Ubuntu 22.04.3 LTS (Jammy)
- 开发工具:Visual Studio 2022 (17.8.0)
- 运行时版本:.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平台 下的 ODBC 配置
- [access_db] # 随意命名,会在项目代码里用到它
- Description=Microsoft Access Database
- Driver=MDBW
- ServerName = localhost
- Database=/root/Database1.mdb # 按你的实际路径改写,要有读写权限
复制代码- [MDBW] # 随意,在odbc.ini文件用到它
- Description=MDBTools Driver Wide # 随意
- Driver=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbcW.so # 按你的实际路径改写
- Setup=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbcW.so # 按你的实际路径改写
- FileUsage=1
- UsageCount=1
- [MDBTools]
- Description=MDBTools Driver # 随意
- Driver=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so # 按你的实际路径改写
- Setup=/usr/lib/x86_64-linux-gnu/odbc/libmdbodbc.so # 按你的实际路径改写
- FileUsage=1
- UsageCount=1
- [ODBC]
- Trace=1
- TraceFile=/tmp/mdb.log # 有写入权限的文件路径
复制代码 Demo 项目代码
- 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>
复制代码- 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);
- }
- }
- }
- }
复制代码 编译和发布 Demo 项目代码
准备工作
- 创建 OdbcForLinuxTestApp 目录
- 将上述两个代码文件放入 OdbcForLinuxTestApp 目录
- 安装 .NET SDK 8.0.100
编译和发布
在 OdbcForLinuxTestApp 目录下,执行命令:- dotnet publish -c Release -f net8.0 -r win-x64 -o ./publish/win-x64 # 如果只考虑 Linux平台,该命令可忽略
- dotnet publish -c Release -f net8.0 -r linux-x64 -o ./publish/linux-x64
复制代码 运行 OdbcForLinuxTestApp
注意:Database1.mdb 数据库文件需要提前放到正确的路径,以 odbc.ini文件 的 Database 配置项为准。
- cd ./publish/linux-x64
- chmod +x OdbcForLinuxTestApp # 授予可执行权限
- ./OdbcForLinuxTestApp
复制代码 输出:- UserName: Allen
- UserName: Joy
复制代码 折腾过程中遇到的问题
- 搜了几个配置例子,有的说 libmdbodbc.so 在 /usr/lib 目录下,
也有的在 /usr/local/lib/odbc 目录下,而我最终是在 /usr/lib/x86_64-linux-gnu/odbc 目录下找到。
- mdbtools 不支持使用列名访问,只能用列索引。
其它
来源:https://www.cnblogs.com/VAllen/archive/2023/11/22/access-mdb-files-in-linux.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|