using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
namespace Apewer.Source
{
///
abstract class DbClient
{
///
public virtual Logger Logger { get; set; }
#region Connection
DbConnection _conn = null;
string _str = null;
///
public Timeout Timeout { get; set; }
///
public DbConnection Connection { get => _conn; }
///
public bool Online { get => _conn == null ? false : (_conn.State == ConnectionState.Open); }
/// 连接字符串。
public string ConnectionString { get => _str; }
///
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;
}
}
///
public void Close()
{
if (_conn != null)
{
if (_transaction != null)
{
if (_autocommit) Commit();
else Rollback();
}
_conn.Close();
_conn.Dispose();
_conn = null;
}
}
///
public void Dispose() { Close(); }
#endregion
#region Transaction
private DbTransaction _transaction = null;
private bool _autocommit = false;
/// 启动事务。
public string Begin(bool commit = true) => Begin(commit, null);
/// 启动事务。
public string Begin(bool commit, Class 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();
}
}
/// 提交事务。
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();
}
}
/// 从挂起状态回滚事务。
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
/// 查询。
public IQuery Query(string sql) => Query(sql, null);
/// 查询。
public IQuery Query(string sql, IEnumerable 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);
}
}
/// 执行。
public IExecute Execute(string sql) => Execute(sql, null);
/// 执行单条 Transact-SQL 语句,并加入参数。
public IExecute Execute(string sql, IEnumerable 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
/// 查询记录。
/// 记录模型。
/// SQL 语句。
public Result