using Apewer.Internals; #if NETFRAMEWORK using System; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.IO; using System.Text; #endif namespace Apewer.Source { /// 用于快速连接 Microsoft Access 数据库的辅助。 public partial class Access { /// 尝试解析 Access 文件的密码。 /// 当操作系统启用随机化内存分配时,此方法可能会产生异常。 public static string[] ParsePassword(string path) => AccessHelper.GetPassword(path); } #if NETFRAMEWORK public partial class Access : IDbClientBase, IDbClientAdo, IDisposable { #region 连接 string _connstr = null; OleDbConnection _connection = null; Timeout _timeout = null; /// 获取或设置日志记录。 public Logger Logger { get; set; } /// 获取或设置超时。 public Timeout Timeout { get => _timeout; } /// 构造函数。 public Access(string connectrionString, Timeout timeout) { _connstr = connectrionString; _timeout = timeout ?? Timeout.Default; } #endregion #region 连接 /// 获取当前的 OldDbConnection 对象。 public IDbConnection Connection { get => _connection; } /// 数据库是否已经连接。 public bool Online { get { if (_connection != null) { if (_connection.State == ConnectionState.Open) return true; } return false; } } /// 连接数据库,若未连接则尝试连接。 /// 错误信息。 public string Connect() { if (_connection == null) { _connection = new OleDbConnection(); _connection.ConnectionString = _connstr; } else { if (_connection.State == ConnectionState.Open) return null; } try { _connection.Open(); if (_connection.State == ConnectionState.Open) return null; } catch (Exception ex) { Logger.Error(nameof(Access), "Connect", ex, _connstr); Close(); return ex.Message; } return "连接失败。"; } /// 释放对象所占用的系统资源。 public void Close() { if (_connection != null) { if (_transaction != null) { if (_autocommit) Commit(); else Rollback(); } _connection.Close(); _connection.Dispose(); _connection = null; } } /// 释放资源。 public void Dispose() => Close(); #endregion #region Transaction private IDbTransaction _transaction = null; private bool _autocommit = false; /// 启动事务。 public string Begin(bool commit = true) => Begin(commit, null); /// 启动事务。 public string Begin(bool commit, Class isolation) { var connect = Connect(); if (connect.NotEmpty()) return connect; if (_transaction != null) return "存在已启动的事务,无法再次启动。"; try { _transaction = isolation ? _connection.BeginTransaction(isolation.Value) : _connection.BeginTransaction(); _autocommit = commit; return null; } catch (Exception ex) { Logger.Error(nameof(Access), "Begin", ex.Message()); return ex.Message(); } } /// 提交事务。 public string Commit() { if (_transaction == null) return "事务不存在。"; try { _transaction.Commit(); RuntimeUtility.Dispose(_transaction); _transaction = null; return null; } catch (Exception ex) { RuntimeUtility.Dispose(_transaction); _transaction = null; Logger.Error(nameof(Access), "Commit", ex.Message()); return ex.Message(); } } /// 从挂起状态回滚事务。 public string Rollback() { if (_transaction == null) return "事务不存在。"; try { _transaction.Rollback(); RuntimeUtility.Dispose(_transaction); _transaction = null; return null; } catch (Exception ex) { RuntimeUtility.Dispose(_transaction); _transaction = null; Logger.Error(nameof(Access), "Rollback", ex.Message); return ex.Message(); } } #endregion #region 查询和执行 /// 使用 SQL 语句进行查询。 public IQuery Query(string sql) => Query(sql, null); /// 使用 SQL 语句进行查询。 public IQuery Query(string sql, IEnumerable parameters) { if (sql.IsBlank()) return Example.InvalidQueryStatement; var connected = Connect(); if (connected.NotEmpty()) return new Query(false, connected); try { using (var command = new OleDbCommand()) { command.Connection = _connection; command.CommandTimeout = Timeout.Query; command.CommandText = sql; if (parameters != null) { foreach (var p in parameters) { if (p != null) command.Parameters.Add(p); } } using (var ds = new DataSet()) { using (var da = new OleDbDataAdapter(sql, _connection)) { var name = "table_" + Guid.NewGuid().ToString("\n"); da.Fill(ds, name); var table = ds.Tables[name]; return new Query(table); } } } } catch (Exception exception) { Logger.Error(nameof(Access), "Query", exception, sql); return new Query(exception); } } /// 执行 SQL 语句。 public IExecute Execute(string sql) => Execute(sql, null); /// 执行 SQL 语句,并加入参数。 public IExecute Execute(string sql, IEnumerable parameters) { if (sql.IsBlank()) return Example.InvalidExecuteStatement; var connected = Connect(); if (connected.NotEmpty()) return new Execute(false, connected); var inTransaction = _transaction != null; if (!inTransaction) Begin(); try { using (var command = new OleDbCommand()) { command.Connection = _connection; command.Transaction = (OleDbTransaction)_transaction; command.CommandTimeout = Timeout.Execute; command.CommandText = sql; if (parameters != null) { foreach (var parameter in parameters) { if (parameter == null) continue; command.Parameters.Add(parameter); } } var rows = command.ExecuteNonQuery(); if (!inTransaction) Commit(); // todo 此处应该检查事务提交产生的错误。 return new Execute(true, rows); } } catch (Exception exception) { Logger.Error(nameof(Access), "Execute", exception, sql); if (!inTransaction) Rollback(); return new Execute(exception); } } #endregion #region Parameter /// 创建参数列表。 public static List NewParameterList() { return new List(); } /// 创建参数。 public static IDbDataParameter CreateParameter(String field, DbType type, Int32 size, Object value) { var p = new OleDbParameter(); p.ParameterName = field; p.DbType = type; p.Size = size; p.Value = value; return p; } /// 创建参数。 public static IDbDataParameter CreateParameter(String field, DbType type, Object value) { var p = new OleDbParameter(); p.ParameterName = field; p.DbType = type; p.Value = value; return p; } #endregion #region protected /// 获取或设置连接字符串。 internal protected static string GenerateCS(string provider, string path, string pass, string jo) { if (!File.Exists(path)) return null; var sb = new StringBuilder(); sb.Append("provider=", provider, "; "); if (!string.IsNullOrEmpty(path)) sb.Append("data source=", path, "; "); if (string.IsNullOrEmpty(pass)) sb.Append("persist security info=false; "); else sb.Append("jet oledb:database password=\"", pass, "\"; "); // Microsoft Access Workgroup Information if (!string.IsNullOrEmpty(jo)) sb.Append("jet oledb:system database=", jo, "; "); return sb.ToString(); } #endregion } /// 使用 Microsoft.Jet.OLEDB.4.0 访问 Access 97 - 2003 数据库文件。 public class AccessJet4 : Access { const string JetOleDB4 = "microsoft.jet.oledb.4.0"; /// 创建 Access 类的新实例。 public AccessJet4(string path, string pass = null, string jo = null, Timeout timeout = null) : base(GenerateCS(JetOleDB4, path, pass, jo), timeout) { } } /// 使用 Microsoft.ACE.OLEDB.12.0 访问 Access 2007 数据库文件。 public class AccessAce12 : Access { const string AceOleDB12 = "microsoft.ace.oledb.12.0"; /// 创建 Access 类的新实例。 public AccessAce12(string path, string pass = null, string jo = null, Timeout timeout = null) : base(GenerateCS(AceOleDB12, path, pass, jo), timeout) { } } #endif }