多数据源(多 Access 库文件)
开发专题 · 同一种 Access,多个 .mdb / .accdb 文件各自连接与查询
本页的多数据源指:在同一个 .NET Framework 4.8 项目里,使用同一种 Access 引擎(OleDb + Jet 或 ACE),同时打开多个不同的库文件(例如 orders.mdb 与 inventory.mdb)。每个文件对应各自的连接字符串与 OleDbConnection,不是一条连接串连所有库。操作文案以 LCode 为准;代码均为 C# 5.0 与 VB.NET。单库 CRUD 见 数据库 · Access;网格 UI 见 数据表单与自定义列。
.mdb/.accdb 里,用一个连接即可。多数据源是多个物理库文件,必须多套连接。
典型场景
| 场景 | 库文件示例 | 说明 |
|---|---|---|
| 业务拆库 | orders.mdb + customers.mdb |
订单与客户分文件,便于备份或权限隔离 |
| 主库 + 配置库 | appdata.mdb + config.mdb |
配置可单独替换,不影响业务数据 |
| 主库 + 日志库 | main.mdb + logs.mdb |
日志膨胀时只归档/清空日志库 |
在 LCode 中准备
- 窗体项目确认已引用
System.Data(OleDb)。Jet 连.mdb时工程宜 x86(或 AnyCPU + 首选 32 位);ACE 须与进程位数一致。细节见 Access 专页。 - 把多个库文件放到输出目录旁,例如
Data\orders.mdb、Data\inventory.mdb(路径可按项目约定调整)。 - 为每个文件各写一条连接字符串(同一
Provider,不同Data Source)。 - 在 LCode 中 编译 → 编译解决方案(F8),再运行验证每个文件都能
Open。
OleDbConnection 去「切换」到另一个文件——应关闭后换连接串,或同时持有两个连接对象。
多条连接字符串(同一 Provider)
下面以 Jet + 两个 .mdb 为例;若用 ACE / .accdb,只需改 Provider 与扩展名,仍保持「一文件一串」。
using System.Data.OleDb;
using System.IO;
using System.Windows.Forms;
string ordersPath = Path.Combine(Application.StartupPath, "Data", "orders.mdb");
string inventoryPath = Path.Combine(Application.StartupPath, "Data", "inventory.mdb");
// 同一 Provider,不同 Data Source = 两个数据源
string ordersConnStr =
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ordersPath + ";";
string inventoryConnStr =
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + inventoryPath + ";";
Imports System.Data.OleDb
Imports System.IO
Imports System.Windows.Forms
Dim ordersPath As String = Path.Combine(Application.StartupPath, "Data", "orders.mdb")
Dim inventoryPath As String = Path.Combine(Application.StartupPath, "Data", "inventory.mdb")
Dim ordersConnStr As String =
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ordersPath & ";"
Dim inventoryConnStr As String =
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & inventoryPath & ";"
实例:分别查询两个 Access 库
假定 orders.mdb 有表 Orders(字段 Id、CustomerName),inventory.mdb 有表 Stock(字段 Sku、Qty)。在按钮点击中各读一次,再汇总提示。参数均用 OleDb 的 ?。
string customer = null;
using (OleDbConnection ordersConn = new OleDbConnection(ordersConnStr))
{
ordersConn.Open();
using (OleDbCommand cmd = new OleDbCommand(
"SELECT TOP 1 CustomerName FROM Orders WHERE Id = ?", ordersConn))
{
cmd.Parameters.AddWithValue("@p1", 1);
object o = cmd.ExecuteScalar();
if (o != null && o != DBNull.Value)
customer = o.ToString();
}
}
int qty = 0;
using (OleDbConnection invConn = new OleDbConnection(inventoryConnStr))
{
invConn.Open();
using (OleDbCommand cmd = new OleDbCommand(
"SELECT TOP 1 Qty FROM Stock WHERE Sku = ?", invConn))
{
cmd.Parameters.AddWithValue("@p1", "A001");
object o = cmd.ExecuteScalar();
if (o != null && o != DBNull.Value)
qty = Convert.ToInt32(o);
}
}
MessageBox.Show(
"订单客户:" + (customer ?? "(无)") +
"\n库存 A001:" + qty.ToString());
Dim customer As String = Nothing
Using ordersConn As New OleDbConnection(ordersConnStr)
ordersConn.Open()
Using cmd As New OleDbCommand(
"SELECT TOP 1 CustomerName FROM Orders WHERE Id = ?", ordersConn)
cmd.Parameters.AddWithValue("@p1", 1)
Dim o As Object = cmd.ExecuteScalar()
If o IsNot Nothing AndAlso o IsNot DBNull.Value Then
customer = o.ToString()
End If
End Using
End Using
Dim qty As Integer = 0
Using invConn As New OleDbConnection(inventoryConnStr)
invConn.Open()
Using cmd As New OleDbCommand(
"SELECT TOP 1 Qty FROM Stock WHERE Sku = ?", invConn)
cmd.Parameters.AddWithValue("@p1", "A001")
Dim o As Object = cmd.ExecuteScalar()
If o IsNot Nothing AndAlso o IsNot DBNull.Value Then
qty = Convert.ToInt32(o)
End If
End Using
End Using
Dim customerText As String = "(无)"
If Not String.IsNullOrEmpty(customer) Then customerText = customer
MessageBox.Show(
"订单客户:" & customerText &
vbCrLf & "库存 A001:" & qty.ToString())
分别绑定到两个 DataGridView
界面可放 dgvOrders 与 dgvStock,各自 Fill 到自己的 DataTable。Access 不能用一条 SQL 直接 JOIN 两个不同的 .mdb 文件(除非做链接表等高级手法);业务关联请在代码里用键拼接,或把需要关联的表放进同一库文件。
using System.Data;
DataTable dtOrders = new DataTable();
using (OleDbConnection c = new OleDbConnection(ordersConnStr))
using (OleDbDataAdapter da = new OleDbDataAdapter(
"SELECT Id, CustomerName, Amount FROM Orders", c))
{
da.Fill(dtOrders);
}
dgvOrders.DataSource = dtOrders;
DataTable dtStock = new DataTable();
using (OleDbConnection c = new OleDbConnection(inventoryConnStr))
using (OleDbDataAdapter da = new OleDbDataAdapter(
"SELECT Sku, [Name], Qty FROM Stock", c))
{
da.Fill(dtStock);
}
dgvStock.DataSource = dtStock;
Imports System.Data
Dim dtOrders As New DataTable()
Using c As New OleDbConnection(ordersConnStr)
Using da As New OleDbDataAdapter(
"SELECT Id, CustomerName, Amount FROM Orders", c)
da.Fill(dtOrders)
End Using
End Using
dgvOrders.DataSource = dtOrders
Dim dtStock As New DataTable()
Using c As New OleDbConnection(inventoryConnStr)
Using da As New OleDbDataAdapter(
"SELECT Sku, [Name], Qty FROM Stock", c)
da.Fill(dtStock)
End Using
End Using
dgvStock.DataSource = dtStock
三个及以上库文件
模式相同:再增加路径与连接串即可。建议用小字典或配置(INI/JSON)保存「逻辑名 → 文件路径」,运行时拼出连接串,避免在代码里散落十多条硬编码路径。读写 INI 见 INI 与 INF。
string BuildAccessConn(string fileName)
{
string path = Path.Combine(Application.StartupPath, "Data", fileName);
return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";";
}
// 使用:BuildAccessConn("orders.mdb") / BuildAccessConn("inventory.mdb") / BuildAccessConn("logs.mdb")
Function BuildAccessConn(fileName As String) As String
Dim path As String = Path.Combine(Application.StartupPath, "Data", fileName)
Return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & path & ";"
End Function
' 使用:BuildAccessConn("orders.mdb") / BuildAccessConn("inventory.mdb")
注意事项
| 主题 | 说明 |
|---|---|
| 一文件一连接 | 每个库文件使用独立的连接串与 OleDbConnection;短开短关或按需长期持有,但不要混用。 |
| 跨库事务 | 两个 Access 文件之间没有自动分布式事务。需要「两边都成功」时自行做补偿(先写可撤销侧等)。 |
| 跨库 JOIN | 普通 SQL 不能直接 JOIN 两个物理 .mdb。应分两次查询,或把表合并进同一库,或使用 Access 链接表(进阶,本页不展开)。 |
| 文件锁 | 每个 .mdb 仍有 Jet 锁文件(如 .ldb)。多进程写同一文件会冲突;多文件可降低互相阻塞,但不能消除单文件锁。 |
| 位数与引擎 | 多个库文件共用同一进程的 Jet/ACE。Jet 仅 32 位;全体库文件路径必须真实存在且进程有读写权限。 |
| SQL 注入 | 用户输入一律参数化(?),不要拼接进 SQL。 |
扩展:异种库(SQLite + Access)
若还需要在同一项目里同时用 SQLite 与 Access,那是异种提供程序叠加:除 Access 的 OleDb 外,还要按 数据库 · SQLite 引用 System.Data.SQLite,并保证进程位数与 Jet/ACE、SQLite.Interop 一致。连接与查询方式与上文相同——「一库一连接」——只是连接类型分别是 OleDbConnection 与 SQLiteConnection。本手册将多 Access 库文件作为多数据源主讲;异种混用按各库专页组合即可。
相关阅读
- 数据库 · Access — OleDb Jet/ACE 引用与单库 CRUD
- 数据表单与自定义列 — DataGridView 绑定
- 数据库 · SQLite — 若需异种混用
- INI 与 INF — 用配置保存多个库路径
- 运行与编译 — 平台目标与输出目录