在Linux平台下使用.NET Core访问Access数据库读取mdb文件数据

  • 在Linux平台下使用.NET Core访问Access数据库读取mdb文件数据已关闭评论
  • 96 次浏览
  • A+
所属分类:.NET技术
摘要

今天有群友在群里问 C# 能不能在 Linux 下访问 Access数据库?我觉得这很有趣,因此研究折腾了一下,也因为很久没有写博文了,所以特意上来写博文分享经验。

今天有群友在群里问 C# 能不能在 Linux 下访问 Access数据库

我觉得这很有趣,因此研究折腾了一下,也因为很久没有写博文了,所以特意上来写博文分享经验。

运行环境

  • 操作系统:Ubuntu 22.04.3 LTS (Jammy)
  • 开发工具:Visual Studio 2022 (17.8.0)
  • 运行时版本:.NET Runtime 8.0
  • 依赖库:unixodbcmdbtoolsodbc-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 配置

  • /etc/odbc.ini
[access_db] # 随意命名,会在项目代码里用到它 Description=Microsoft Access Database Driver=MDBW ServerName = localhost Database=/root/Database1.mdb # 按你的实际路径改写,要有读写权限 
  • /etc/odbcinst.ini
[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> 
  • 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);             }         }     } } 

编译和发布 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 

折腾过程中遇到的问题

  1. 搜了几个配置例子,有的说 libmdbodbc.so/usr/lib 目录下,
    也有的在 /usr/local/lib/odbc 目录下,而我最终是在 /usr/lib/x86_64-linux-gnu/odbc 目录下找到。

  2. mdbtools 不支持使用列名访问,只能用列索引。

其它