|
|
using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Text;
namespace Apewer.Source {
/// <summary></summary>
abstract class DbClient {
/// <summary></summary>
public virtual Logger Logger { get; set; }
#region Connection
DbConnection _conn = null; string _str = null;
/// <summary></summary>
public Timeout Timeout { get; set; }
/// <summary></summary>
public DbConnection Connection { get => _conn; }
/// <summary></summary>
public bool Online { get => _conn == null ? false : (_conn.State == ConnectionState.Open); }
/// <summary>连接字符串。</summary>
public string ConnectionString { get => _str; }
/// <summary></summary>
public virtual string Connect() { if (_conn == null) { _str = GetConnectionString(); _conn = NewConnection(); _conn.ConnectionString = _str; } else { if (_conn.State == ConnectionState.Open) return null; }
try { _conn.Open(); switch (_conn.State) { case ConnectionState.Open: return null; default: return $"连接失败,当前处于 {_conn.State} 状态。"; } } catch (Exception ex) { Logger.Error(this, "Connect", ex, _conn.ConnectionString); Close(); return ex.Message; } }
/// <summary></summary>
public void Close() { if (_conn != null) { if (_transaction != null) { if (_autocommit) Commit(); else Rollback(); } _conn.Close(); _conn.Dispose(); _conn = null; } }
/// <summary></summary>
public void Dispose() { Close(); }
#endregion
#region Transaction
private DbTransaction _transaction = null; private bool _autocommit = false;
/// <summary>启动事务。</summary>
public string Begin(bool commit = true) => Begin(commit, null);
/// <summary>启动事务。</summary>
public string Begin(bool commit, Class<System.Data.IsolationLevel> isolation) { if (Connect() != null) return "未连接。"; if (_transaction != null) return "存在已启动的事务,无法再次启动。"; try { _transaction = isolation ? _conn.BeginTransaction(isolation.Value) : _conn.BeginTransaction(); _autocommit = commit; return null; } catch (Exception ex) { Logger.Error(this, "Commit", ex.Message()); return ex.Message(); } }
/// <summary>提交事务。</summary>
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(this, "Commit", ex.Message()); return ex.Message(); } }
/// <summary>从挂起状态回滚事务。</summary>
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(this, "Rollback", ex.Message()); return ex.Message(); } }
#endregion
#region ADO
/// <summary>查询。</summary>
public IQuery Query(string sql) => Query(sql, null);
/// <summary>查询。</summary>
public IQuery Query(string sql, IEnumerable<IDataParameter> parameters) { if (TextUtility.IsBlank(sql)) return new Query(false, "语句无效。"); var connected = Connect(); if (connected.NotEmpty()) return new Query(false, connected);
try { using (var command = NewCommand()) { command.Connection = _conn; if (Timeout != null) command.CommandTimeout = Timeout.Query; command.CommandText = sql; if (parameters != null) { foreach (var parameter in parameters) { if (parameter != null) command.Parameters.Add(parameter); } } using (var ds = new DataSet()) { using (var da = NewDataAdapter(sql)) { var name = "table_" + Guid.NewGuid().ToString("n"); da.Fill(ds, name); var table = ds.Tables[name]; return new Query(table, true); } } } } catch (Exception exception) { Logger.Error(this, "Query", exception, sql); return new Query(exception); } }
/// <summary>执行。</summary>
public IExecute Execute(string sql) => Execute(sql, null);
/// <summary>执行单条 Transact-SQL 语句,并加入参数。</summary>
public IExecute Execute(string sql, IEnumerable<IDataParameter> parameters) { if (TextUtility.IsBlank(sql)) 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 = NewCommand()) { command.Connection = _conn; command.Transaction = (DbTransaction)_transaction; if (Timeout != null) command.CommandTimeout = Timeout.Execute; command.CommandText = sql; if (parameters != null) { foreach (var parameter in parameters) { if (parameter != null) command.Parameters.Add(parameter); } } var rows = command.ExecuteNonQuery(); if (!inTransaction) Commit(); // todo 此处应该检查事务提交产生的错误。
return new Execute(true, rows); } } catch (Exception exception) { Logger.Error(this, "Execute", exception, sql); if (!inTransaction) Rollback(); return new Execute(exception); } }
#endregion
#region ORM - Query
/// <summary>查询记录。</summary>
/// <param name="model">记录模型。</param>
/// <param name="sql">SQL 语句。</param>
public Result<object[]> Query(Type model, string sql) { if (_conn == null) return new Result<object[]>("连接无效。"); if (model == null) return new Result<object[]>("数据模型类型无效。"); if (string.IsNullOrEmpty(sql)) return new Result<object[]>("SQL 语句无效。");
var query = Query(sql); var result = null as Result<object[]>;
if (query.Success) { try { var array = OrmHelper.Fill(query, model); result = new Result<object[]>(array); } catch (Exception ex) { result = new Result<object[]>(ex); } } else { result = new Result<object[]>(query.Message); }
query.Dispose(); return result; }
/// <summary></summary>
public Result<T[]> Query<T>(string sql) where T : class, new() { var query = Query(sql); if (!query.Success) return new Result<T[]>(query.Message); var records = query.Fill<T>(); query.Dispose();
var result = new Result<T[]>(records); return result; }
#endregion
#region Static
/// <summary>对文本转义,符合 SQL 安全性。可根据字段类型限制 UTF-8 字节数,默认为 0 时不限制字节数。</summary>
protected static string Escape(string text, int bytes = 0) { if (text.IsEmpty()) return "";
var t = text ?? ""; t = t.Replace("\\", "\\\\"); t = t.Replace("'", "\\'"); t = t.Replace("\n", "\\n"); t = t.Replace("\r", "\\r"); t = t.Replace("\b", "\\b"); t = t.Replace("\t", "\\t"); t = t.Replace("\f", "\\f");
if (bytes > 5) { if (t.Bytes(Encoding.UTF8).Length > bytes) { while (true) { t = t.Substring(0, t.Length - 1); if (t.Bytes(Encoding.UTF8).Length <= (bytes - 4)) break; } t = t + " ..."; } }
return t; }
#endregion
/// <summary></summary>
protected abstract string GetConnectionString();
/// <summary></summary>
protected abstract DbConnection NewConnection();
/// <summary></summary>
protected abstract DbDataAdapter NewDataAdapter(string sql);
/// <summary></summary>
protected abstract DbCommand NewCommand();
}
}
|