OleDbConnection 连 Access MDB 必须指定 Provider(如 Jet 4.0 或 ACE)和 Data Source,且平台目标需匹配驱动位数(Jet 仅支持 x86);参数只能用 ? 占位,不支持命名参数;读取推荐 OleDbDataReader,避免 DataTable.Load() 全表加载;注意文件锁、权限及路径引号包裹。

用 OleDbConnection 连 Access MDB 文件,连接字符串必须带 Provider 和 Data Source
Access 不是 SQL Server,不能用 SqlConnection;得靠 OleDb 提供商。常见错误是照抄 SQL Server 的写法,或者漏掉 Provider——这会导致 "The 'Microsoft.Jet.OLEDB.4.0' provider is not registered" 或 "Could not find installable ISAM"。
32/64 位运行时必须匹配驱动:VS 默认编译为 Any CPU,但 Jet 4.0(MDB)只有 32 位,ACE 驱动(ACCDB)有 32/64 双版本。如果程序跑在 64 位系统上却没改目标平台,会直接报错。
- Jet 4.0(仅支持 .mdb):
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\db.mdb; - ACE(支持 .mdb 和 .accdb):
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\db.accdb;(需装 Access Database Engine) - 项目属性 → Build → Platform target 必须设为
x86(用 Jet)或按 ACE 版本选x86/x64
OleDbCommand 执行查询时,参数名无效,必须用 ? 占位
Access 的 OleDb 实现不支持命名参数(比如 @id),所有参数一律按顺序用 ?。写成 "SELECT * FROM Users WHERE Name = @name" 看似合理,实际会查不到结果甚至报语法错误。
另外,Access 对 SQL 语法限制多:不支持 OFFSET FETCH、窗口函数、CTE;TOP 写法也和 SQL Server 不同(不需要括号)。
- 正确写法:
SELECT TOP 10 * FROM Logs ORDER BY Time DESC - 参数化插入:
INSERT INTO Users (Name, Age) VALUES (?, ?),然后按顺序调用cmd.Parameters.Add("dummy", OleDbType.VarChar).Value = "Alice"(参数名只是占位,实际忽略) - 别用
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")拼 SQL —— 容易被注入,且格式受区域设置影响;OleDb 能自动处理DateTime类型参数
读取数据优先用 OleDbDataReader,别一上来就 DataTable.Load()
Access 是文件数据库,没有连接池和服务器端游标优化。DataTable.Load() 会把整张表拉进内存,哪怕只查一行;而 OleDbDataReader 是流式读取,边读边处理,内存友好得多。
还容易忽略的是字段类型映射:Access 的 Yes/No 字段读出来是 Boolean,但空值会变成 DBNull.Value;Text 字段默认长度是 255,超长会被截断(建表时没设 Size 属性的话)。
- 安全读取布尔字段:
reader["Active"] == DBNull.Value ? false : (bool)reader["Active"] - 避免隐式转换异常:用
reader.GetValue(i)或reader.GetFieldType(i)查类型,别硬转(int)reader["ID"] - 如果真要填
DataTable,确保OleDbDataAdapter.Fill()前已打开连接,且连接生命周期可控(Access 不支持并发写入)
写入失败常见原因:文件被占用、权限不足、路径含中文或空格
Access MDB 是单文件数据库,Windows 下只要有一个进程(包括资源管理器预览窗格、另一个 C# 进程、甚至 Excel 正在打开它)锁着文件,OleDbConnection.Open() 就会卡住或抛出 "Cannot open database"。
另外,.NET 默认以当前用户身份访问文件,如果 MDB 在 C:\Program Files 或网络路径下,可能因 UAC 或共享权限拒绝写入;路径里有空格或中文倒不是问题,但连接字符串里必须用英文引号包裹整个 Data Source 值(OleDb 解析器很老,不严谨)。
- 检查是否被占用:任务管理器看有没有
EXCEL.EXE、MSACCESS.EXE,或用Process Explorer搜索文件句柄 - 开发时把 MDB 放到项目
bin\Debug下,用相对路径:Data Source=|DataDirectory|\app.mdb,并在启动时设AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory) - 写操作前确认连接字符串加了
Mode=ReadWrite(默认就是,但显式写上更安心)
Access 的事务支持弱,OleDbTransaction 只能用于单连接内的操作,跨多个 OleDbCommand 时别指望回滚能覆盖所有更改;真正需要强一致性的场景,该换 SQLite 或轻量级 SQL Server Express。











