Browse Source

Apewer-6.7.4

dev
王厅 2 years ago
parent
commit
59e4e98a60
  1. 71
      Apewer.Source/Source/DbClient.cs
  2. 39
      Apewer.Source/Source/MySql.cs
  3. 39
      Apewer.Source/Source/SqlClient.cs
  4. 3
      Apewer.Windows/Internals/Interop/Kernel32.cs
  5. 10
      Apewer.Windows/Internals/Interop/LASTINPUTINFO.cs
  6. 6
      Apewer.Windows/Internals/Interop/User32.cs
  7. 9
      Apewer.Windows/WindowsUtility.cs
  8. 2
      Apewer/Apewer.props
  9. 3
      Apewer/Source/IDbAdo.cs
  10. 47
      Apewer/Source/SourceUtility.cs
  11. 10
      Apewer/Source/Timeout.cs
  12. 13
      ChangeLog.md

71
Apewer.Source/Source/DbClient.cs

@ -20,49 +20,80 @@ namespace Apewer.Source
#region Connection
string _key = TextUtility.Key();
Timeout _timeout = null;
IDbConnection _conn = null;
bool _disposed = false;
/// <summary></summary>
internal protected object Locker = new object();
/// <summary>此连接的唯一标识。</summary>
public virtual string Key { get => _key; }
/// <summary></summary>
public Timeout Timeout { get => _timeout; set => _timeout = value ?? Timeout.Default; }
public virtual Timeout Timeout { get => _timeout; set => _timeout = value ?? Timeout.Default; }
/// <summary>获取当前的 SqlConnection 对象。</summary>
public IDbConnection Connection { get => _conn; }
/// <summary></summary>
public bool Online { get => _conn == null ? false : (_conn.State == ConnectionState.Open); }
/// <summary>此连接已释放。</summary>
public virtual bool Disposed { get => _disposed; }
/// <summary>连接处于打开状态。</summary>
public virtual bool Online { get => _conn == null ? false : (_conn.State == ConnectionState.Open); }
/// <summary>连接字符串。</summary>
public abstract string ConnectionString { get; }
/// <summary>关闭连接后,执行的方法。</summary>
public virtual Action<IDbAdo> OnClosed { get; set; }
/// <summary>连接数据库,若未连接则尝试连接,获取连接成功的状态。</summary>
public string Connect()
{
if (_conn == null) _conn = GetConnection();
if (_disposed)
{
if (ThrowAdoException) throw new ObjectDisposedException(GetType().Name);
return "当前连接已释放,无法再次连接。";
}
if (_conn == null) _conn = GetConnection();
if (_conn.State == ConnectionState.Open) return null;
if (ThrowAdoException)
{
_conn.Open();
if (_conn.State != ConnectionState.Open)
{
var message = $"连接后状态为 {_conn.State},无法验证打开状态。";
Logger.Error(this, "Connect", message);
throw new SqlException(message);
}
return null;
}
try
{
_conn.Open();
if (_conn.State == ConnectionState.Open) return null;
var message = $"连接后状态为 {_conn.State},无法验证打开状态。";
Logger.Error(this, "Connect", message);
return "连接失败," + message;
if (_conn.State != ConnectionState.Open)
{
var message = $"连接后状态为 {_conn.State},无法验证打开状态。";
Logger.Error(this, "Connect", message);
return "连接失败," + message;
}
return null;
}
catch (Exception ex)
{
Logger.Error(this, "Connect", ex.Message);
Close();
if (ThrowAdoException) throw;
return ex.Message;
}
}
/// <summary>更改已打开的数据库。</summary>
public string Change(string store)
public virtual string Change(string store)
{
if (store.IsEmpty())
{
@ -89,6 +120,9 @@ namespace Apewer.Source
/// <summary>关闭连接,并释放对象所占用的系统资源。</summary>
public virtual void Close()
{
if (_disposed) return;
_disposed = true;
if (_conn != null)
{
if (_transaction != null)
@ -97,8 +131,10 @@ namespace Apewer.Source
else Rollback();
_transaction = null;
}
try { ClearPool(); } catch { }
try { _conn.Close(); } catch { }
var onClosed = OnClosed;
if (onClosed != null) onClosed.Invoke(this);
}
}
@ -108,9 +144,6 @@ namespace Apewer.Source
Close();
}
/// <summary>清理连接池,释放当前连接。</summary>
protected virtual void ClearPool(bool all = false) { }
#endregion
#region Transaction
@ -121,7 +154,7 @@ namespace Apewer.Source
private bool _autocommit = false;
/// <summary>获取已启动的事务。</summary>
public IDbTransaction Transaction { get => _transaction; }
public virtual IDbTransaction Transaction { get => _transaction; }
string Begin(bool commit, Class<IsolationLevel> isolation)
{
@ -160,7 +193,7 @@ namespace Apewer.Source
/// <para>Unspecified = -1<br />正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。</para>
/// </summary>
/// <param name="commit">在连接的生命周期结束时未结束事务,指定 TRUE 将自动提交,指定 FALSE 将自动回滚。</param>
public string Begin(bool commit = false) => Begin(commit, null);
public virtual string Begin(bool commit = false) => Begin(commit, null);
/// <summary>
/// <para>使用指定的事务锁定行为启动事务。</para>
@ -174,10 +207,10 @@ namespace Apewer.Source
/// </summary>
/// <param name="commit">在连接的生命周期结束时未结束事务,指定 TRUE 将自动提交,指定 FALSE 将自动回滚。</param>
/// <param name="isolation">指定事务锁定行为,不指定时将使用默认值。</param>
public string Begin(bool commit, IsolationLevel isolation) => Begin(commit, new Class<IsolationLevel>(isolation));
public virtual string Begin(bool commit, IsolationLevel isolation) => Begin(commit, new Class<IsolationLevel>(isolation));
/// <summary>提交事务。</summary>
public string Commit()
public virtual string Commit()
{
if (_transaction == null)
{
@ -203,7 +236,7 @@ namespace Apewer.Source
}
/// <summary>从挂起状态回滚事务。</summary>
public string Rollback()
public virtual string Rollback()
{
if (_transaction == null)
{

39
Apewer.Source/Source/MySql.cs

@ -63,14 +63,6 @@ namespace Apewer.Source
_connstr = cs;
}
/// <summary></summary>
protected override void ClearPool(bool all = false)
{
var conn = Connection as MySqlConnection;
if (conn != null) MySqlConnection.ClearPool(conn);
if (all) MySqlConnection.ClearAllPools();
}
#endregion
#region override
@ -425,6 +417,37 @@ namespace Apewer.Source
#region static
/// <summary>清空与指定连接关联的连接池。</summary>
public static void ClearPool(IDbConnection connection)
{
var special = connection as MySqlConnection;
if (special != null)
{
try
{
MySqlConnection.ClearPool(special);
}
catch { }
}
}
/// <summary>清空与指定连接关联的连接池。</summary>
public static void ClearPool(IDbAdo instance)
{
var connection = instance?.Connection;
if (connection != null) ClearPool(connection);
}
/// <summary>清空连接池。</summary>
public static void ClearAllPools()
{
try
{
MySqlConnection.ClearAllPools();
}
catch { }
}
/// <summary></summary>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>

39
Apewer.Source/Source/SqlClient.cs

@ -62,14 +62,6 @@ namespace Apewer.Source
_connstr = cs;
}
/// <summary></summary>
protected override void ClearPool(bool all = false)
{
var conn = Connection as SqlConnection;
if (conn != null) SqlConnection.ClearPool(conn);
if (all) SqlConnection.ClearAllPools();
}
#endregion
#region override
@ -292,6 +284,37 @@ namespace Apewer.Source
#region special
/// <summary>清空与指定连接关联的连接池。</summary>
public static void ClearPool(IDbConnection connection)
{
var special = connection as SqlConnection;
if (special != null)
{
try
{
SqlConnection.ClearPool(special);
}
catch { }
}
}
/// <summary>清空与指定连接关联的连接池。</summary>
public static void ClearPool(IDbAdo instance)
{
var connection = instance?.Connection;
if (connection != null) ClearPool(connection);
}
/// <summary>清空连接池。</summary>
public static void ClearAllPools()
{
try
{
SqlConnection.ClearAllPools();
}
catch { }
}
/// <summary>获取列信息。</summary>
public ColumnInfo[] ColumnsInfo(string tableName)
{

3
Apewer.Windows/Internals/Interop/Kernel32.cs

@ -34,6 +34,9 @@ namespace Apewer.Internals.Interop
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetFileSize(IntPtr hFile, out uint highSize);
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

10
Apewer.Windows/Internals/Interop/LASTINPUTINFO.cs

@ -0,0 +1,10 @@
namespace Apewer.Internals.Interop
{
internal struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
}
}

6
Apewer.Windows/Internals/Interop/User32.cs

@ -100,6 +100,9 @@ namespace Apewer.Internals.Interop
[DllImport("User32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetKeyState(int KeyCode);
[DllImport("User32.dll")]
public static extern bool GetLastInputInfo(ref LASTINPUTINFO Dummy);
[DllImport("user32.dll", EntryPoint = "GetSystemMenu")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);
@ -144,6 +147,9 @@ namespace Apewer.Internals.Interop
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
[DllImport("User32.dll")]
public static extern bool LockWorkStation();
/// <summary></summary>
/// <param name="type"></param>
/// <returns></returns>

9
Apewer.Windows/WindowsUtility.cs

@ -550,6 +550,15 @@ namespace Apewer
User32.ShowWindow(i, 1);
}
/// <summary>获取系统空闲的毫秒数。</summary>
public static uint GetIdleTime()
{
LASTINPUTINFO LastUserAction = new LASTINPUTINFO();
LastUserAction.cbSize = (uint)Marshal.SizeOf(LastUserAction);
User32.GetLastInputInfo(ref LastUserAction);
return ((uint)Environment.TickCount - LastUserAction.dwTime);
}
#endregion
#region 鼠标。

2
Apewer/Apewer.props

@ -9,7 +9,7 @@
<Description></Description>
<RootNamespace>Apewer</RootNamespace>
<Product>Apewer Libraries</Product>
<Version>6.7.3</Version>
<Version>6.7.4</Version>
</PropertyGroup>
<!-- 生成 -->

3
Apewer/Source/IDbAdo.cs

@ -25,6 +25,9 @@ namespace Apewer.Source
/// <summary>数据库当前在线,表示连接可用。</summary>
bool Online { get; }
/// <summary>关闭连接后,执行的方法。</summary>
Action<IDbAdo> OnClosed { get; set; }
/// <summary>连接数据库,若未连接则尝试连接,返回错误信息。</summary>
string Connect();

47
Apewer/Source/SourceUtility.cs

@ -453,7 +453,7 @@ namespace Apewer.Source
/// <param name="sql">SQL 语句。</param>
/// <param name="parameters">SQL 参数。</param>
/// <exception cref="ArgumentNullException"></exception>
public static IQuery Query(this IDbClient dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
public static IQuery Query(this IDbAdo dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (sql.IsEmpty()) throw new ArgumentNullException(nameof(sql));
@ -467,7 +467,7 @@ namespace Apewer.Source
/// <param name="sql">SQL 语句。</param>
/// <param name="parameters">参数容器,每个属性表示一个 SQL 参数。此方法将会自动补足参数名称的 @ 前缀。</param>
/// <exception cref="ArgumentNullException"></exception>
public static IQuery Query(this IDbClient dbClient, string sql, object parameters = null)
public static IQuery Query(this IDbAdo dbClient, string sql, object parameters = null)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (sql.IsEmpty()) throw new ArgumentNullException(nameof(sql));
@ -490,7 +490,7 @@ namespace Apewer.Source
/// <summary>执行 SQL 语句,并加入参数。</summary>
/// <exception cref="ArgumentNullException"></exception>
public static IExecute Execute(this IDbClient dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters, bool autoTransaction = false)
public static IExecute Execute(this IDbAdo dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters, bool autoTransaction = false)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (sql.IsEmpty()) throw new ArgumentNullException(nameof(sql));
@ -505,7 +505,7 @@ namespace Apewer.Source
/// <param name="parameters">参数容器,每个属性表示一个 SQL 参数。此方法将会自动补足参数名称的 @ 前缀。</param>
/// <param name="autoTransaction">自动使用事务。</param>
/// <exception cref="ArgumentNullException"></exception>
public static IExecute Execute(this IDbClient dbClient, string sql, object parameters = null, bool autoTransaction = false)
public static IExecute Execute(this IDbAdo dbClient, string sql, object parameters = null, bool autoTransaction = false)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (sql.IsEmpty()) throw new ArgumentNullException(nameof(sql));
@ -524,10 +524,45 @@ namespace Apewer.Source
#endregion
#region Transaction
/// <summary>启动事务,执行指定的过程并在完成后提交事务。若过程被异常打断,则回滚事务。</summary>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="SqlException"></exception>
public static void InTransaction<T>(this IDbAdo source, Action action)
{
// 检查参数。
if (source == null) throw new ArgumentNullException(nameof(source), "数据源无效。");
if (action == null) throw new ArgumentNullException(nameof(action), "没有指定要执行的过程。");
// 启动事务。
var begin = source.Begin();
if (begin.NotEmpty()) throw new SqlException("无法启动事务:" + begin);
try
{
// 在事务内运行。
action.Invoke();
// 执行成功,提交事务。
var commit = source.Commit();
if (!string.IsNullOrEmpty(commit)) throw new SqlException(commit);
}
catch (Exception ex)
{
// 执行失败,回滚事务。
try { source.Rollback(); } catch { }
throw ex;
}
}
#endregion
#region Parameter
/// <exception cref="ArgumentNullException"></exception>
static List<IDataParameter> ParametersByProperites(IDbClient dbClient, string sql, object parameters)
static List<IDataParameter> ParametersByProperites(IDbAdo dbClient, string sql, object parameters)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (parameters == null) return null;
@ -574,7 +609,7 @@ namespace Apewer.Source
}
/// <exception cref="ArgumentNullException"></exception>
static List<IDataParameter> Parameters(IDbClient dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
static List<IDataParameter> Parameters(IDbAdo dbClient, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
{
if (dbClient == null) throw new ArgumentNullException(nameof(dbClient));
if (parameters == null) return null;

10
Apewer/Source/Timeout.cs

@ -18,29 +18,29 @@ namespace Apewer.Source
_execute = execute;
}
/// <summary>连接。</summary>
/// <summary>连接超时秒数。</summary>
public int Connect
{
get { return _connect; }
set { _connect = (value >= 0) ? value : 0; }
}
/// <summary>查询。</summary>
/// <summary>查询超时秒数。</summary>
public int Query
{
get { return _query; }
set { _query = (value >= 0) ? value : 0; }
}
/// <summary>执行。</summary>
/// <summary>执行超时秒数。</summary>
public int Execute
{
get { return _execute; }
set { _execute = (value >= 0) ? value : 0; }
}
/// <summary>默认超时设置:连接 5000、查询 60000,执行 60000。</summary>
public static Timeout Default { get => new Timeout(5000, 60000, 60000); }
/// <summary>默认超时设置:连接 5 秒、查询 3600 秒,执行 3600 秒。</summary>
public static Timeout Default { get => new Timeout(5, 3600, 3600); }
}

13
ChangeLog.md

@ -1,6 +1,16 @@

### 最新提交
### 6.7.4
- 问题修正
- Source:修正了 Timeout 的默认值,已经改为连接 5 秒,查询、执行 3600 秒。
- 新特性
- Source:增加扩展方法 IDbAdo.InTransaction;
- WindowsUtility:增加 GetIdleTime 方法,获取系统空闲毫秒数。
- 已迁移特性
- Source:调用 Close 后,不再允许再次连接(之前可以再次发起连接),错误的操作将返回错误信息或抛出 ObjectDisposedException;
- Source:分离 ClearPool 方法,去除自动执行,现在可以使用 IDbAdo.OnClosed 属性设置关闭连接之后的回调。
### 6.7.3
- 问题修正
- ClockUtility:修正 Query.DateTime() 出现 null.ToString 问题;
@ -32,7 +42,8 @@
- 迁移 Query 方法,改为 DataTable 的扩展方法。
- 弃用特性
- 去除 object 转数值类型的扩展方法,现在扩展方法只支持明确支持的类型。
- Class<T> 去除了无用的 HasValue 属性
- Class<T> 去除了无用的 HasValue 属性。
### 6.7.2
- 问题修正

Loading…
Cancel
Save