mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 12:28:15 +08:00
- 增加 ISelect.ForUpdate 排他更新锁(根据数据库类型的规则,见代码注释);
- 完善 SqlServer WithLock 功能,组合多种使用 | 枚举相联;
This commit is contained in:
@ -1154,6 +1154,20 @@
|
||||
<param name="name">零个或多个过滤器名字</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.ISelect0`2.ForUpdate(System.Boolean)">
|
||||
<summary>
|
||||
排他更新锁<para></para>
|
||||
注意:务必在开启事务后使用该功能<para></para>
|
||||
MySql: for update<para></para>
|
||||
SqlServer: With(UpdLock, RowLock, NoWait)<para></para>
|
||||
PostgreSQL: for update nowait<para></para>
|
||||
Oracle: for update nowait<para></para>
|
||||
Sqlite: 无效果<para></para>
|
||||
达梦: for update nowait
|
||||
</summary>
|
||||
<param name="nowait">noawait</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSql.ISelect0`2.GroupBy(System.String,System.Object)">
|
||||
<summary>
|
||||
按原生sql语法分组,GroupBy("concat(name, ?cc)", new { cc = 1 })
|
||||
@ -1956,7 +1970,7 @@
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.Transaction(System.Action)">
|
||||
<summary>
|
||||
开启事务(不支持异步),60秒未执行完将自动提交
|
||||
开启事务(不支持异步),60秒未执行完成(可能)被其他线程事务自动提交
|
||||
</summary>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
@ -1964,7 +1978,7 @@
|
||||
<summary>
|
||||
开启事务(不支持异步)
|
||||
</summary>
|
||||
<param name="timeout">超时,未执行完将自动提交</param>
|
||||
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
<member name="M:FreeSql.IAdo.Transaction(System.Data.IsolationLevel,System.TimeSpan,System.Action)">
|
||||
@ -1973,7 +1987,7 @@
|
||||
</summary>
|
||||
<param name="isolationLevel"></param>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
<param name="timeout">超时,未执行完将自动提交</param>
|
||||
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
</member>
|
||||
<member name="P:FreeSql.IAdo.TransactionCurrentThread">
|
||||
<summary>
|
||||
@ -2974,7 +2988,7 @@
|
||||
</member>
|
||||
<member name="M:IFreeSql.Transaction(System.Action)">
|
||||
<summary>
|
||||
开启事务(不支持异步),60秒未执行完将自动提交
|
||||
开启事务(不支持异步),60秒未执行完成(可能)被其他线程事务自动提交
|
||||
</summary>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
@ -2982,7 +2996,7 @@
|
||||
<summary>
|
||||
开启事务(不支持异步)
|
||||
</summary>
|
||||
<param name="timeout">超时,未执行完将自动提交</param>
|
||||
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
</member>
|
||||
<member name="M:IFreeSql.Transaction(System.Data.IsolationLevel,System.TimeSpan,System.Action)">
|
||||
@ -2991,7 +3005,7 @@
|
||||
</summary>
|
||||
<param name="isolationLevel"></param>
|
||||
<param name="handler">事务体 () => {}</param>
|
||||
<param name="timeout">超时,未执行完将自动提交</param>
|
||||
<param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
</member>
|
||||
<member name="P:IFreeSql.Ado">
|
||||
<summary>
|
||||
|
@ -250,6 +250,20 @@ namespace FreeSql
|
||||
/// <returns></returns>
|
||||
TSelect DisableGlobalFilter(params string[] name);
|
||||
|
||||
/// <summary>
|
||||
/// 排他更新锁<para></para>
|
||||
/// 注意:务必在开启事务后使用该功能<para></para>
|
||||
/// MySql: for update<para></para>
|
||||
/// SqlServer: With(UpdLock, RowLock, NoWait)<para></para>
|
||||
/// PostgreSQL: for update nowait<para></para>
|
||||
/// Oracle: for update nowait<para></para>
|
||||
/// Sqlite: 无效果<para></para>
|
||||
/// 达梦: for update nowait
|
||||
/// </summary>
|
||||
/// <param name="nowait">noawait</param>
|
||||
/// <returns></returns>
|
||||
TSelect ForUpdate(bool nowait = false);
|
||||
|
||||
/// <summary>
|
||||
/// 按原生sql语法分组,GroupBy("concat(name, ?cc)", new { cc = 1 })
|
||||
/// </summary>
|
||||
|
@ -34,14 +34,14 @@ namespace FreeSql
|
||||
|
||||
#region 事务
|
||||
/// <summary>
|
||||
/// 开启事务(不支持异步),60秒未执行完将自动提交
|
||||
/// 开启事务(不支持异步),60秒未执行完成(可能)被其他线程事务自动提交
|
||||
/// </summary>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
void Transaction(Action handler);
|
||||
/// <summary>
|
||||
/// 开启事务(不支持异步)
|
||||
/// </summary>
|
||||
/// <param name="timeout">超时,未执行完将自动提交</param>
|
||||
/// <param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
void Transaction(TimeSpan timeout, Action handler);
|
||||
/// <summary>
|
||||
@ -49,7 +49,7 @@ namespace FreeSql
|
||||
/// </summary>
|
||||
/// <param name="isolationLevel"></param>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
/// <param name="timeout">超时,未执行完将自动提交</param>
|
||||
/// <param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
void Transaction(IsolationLevel isolationLevel, TimeSpan timeout, Action handler);
|
||||
/// <summary>
|
||||
/// 当前线程的事务
|
||||
|
@ -87,14 +87,14 @@ public interface IFreeSql : IDisposable
|
||||
IDelete<T1> Delete<T1>(object dywhere) where T1 : class;
|
||||
|
||||
/// <summary>
|
||||
/// 开启事务(不支持异步),60秒未执行完将自动提交
|
||||
/// 开启事务(不支持异步),60秒未执行完成(可能)被其他线程事务自动提交
|
||||
/// </summary>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
void Transaction(Action handler);
|
||||
/// <summary>
|
||||
/// 开启事务(不支持异步)
|
||||
/// </summary>
|
||||
/// <param name="timeout">超时,未执行完将自动提交</param>
|
||||
/// <param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
void Transaction(TimeSpan timeout, Action handler);
|
||||
/// <summary>
|
||||
@ -102,7 +102,7 @@ public interface IFreeSql : IDisposable
|
||||
/// </summary>
|
||||
/// <param name="isolationLevel"></param>
|
||||
/// <param name="handler">事务体 () => {}</param>
|
||||
/// <param name="timeout">超时,未执行完将自动提交</param>
|
||||
/// <param name="timeout">超时,未执行完成(可能)被其他线程事务自动提交</param>
|
||||
void Transaction(IsolationLevel isolationLevel, TimeSpan timeout, Action handler);
|
||||
|
||||
/// <summary>
|
||||
|
@ -26,6 +26,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
protected List<SelectTableInfo> _tables = new List<SelectTableInfo>();
|
||||
protected List<Func<Type, string, string>> _tableRules = new List<Func<Type, string, string>>();
|
||||
protected Func<Type, string, string> _aliasRule;
|
||||
protected string _tosqlAppendContent;
|
||||
protected StringBuilder _join = new StringBuilder();
|
||||
protected IFreeSql _orm;
|
||||
protected CommonUtils _commonUtils;
|
||||
@ -990,6 +991,36 @@ namespace FreeSql.Internal.CommonProvider
|
||||
}
|
||||
return this as TSelect;
|
||||
}
|
||||
public TSelect ForUpdate(bool noawait = false)
|
||||
{
|
||||
if (_transaction == null && _orm.Ado.TransactionCurrentThread == null)
|
||||
throw new Exception("安全起见,请务必在事务开启之后,再使用 ForUpdate");
|
||||
switch (_orm.Ado.DataType)
|
||||
{
|
||||
case DataType.MySql:
|
||||
case DataType.OdbcMySql:
|
||||
_tosqlAppendContent = " for update";
|
||||
break;
|
||||
case DataType.SqlServer:
|
||||
case DataType.OdbcSqlServer:
|
||||
_aliasRule = (_, old) => $"{old} With(UpdLock, RowLock{(noawait ? ", NoWait" : "")})";
|
||||
break;
|
||||
case DataType.PostgreSQL:
|
||||
case DataType.OdbcPostgreSQL:
|
||||
_tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}";
|
||||
break;
|
||||
case DataType.Oracle:
|
||||
case DataType.OdbcOracle:
|
||||
_tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}";
|
||||
break;
|
||||
case DataType.Sqlite:
|
||||
break;
|
||||
case DataType.OdbcDameng:
|
||||
_tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}";
|
||||
break;
|
||||
}
|
||||
return this as TSelect;
|
||||
}
|
||||
#region common
|
||||
|
||||
protected TMember InternalAvg<TMember>(Expression exp) => this.ToList<TMember>($"avg({_commonExpression.ExpressionSelectColumn_MemberAccess(_tables, null, SelectTableInfoType.From, exp, true, null)})").FirstOrDefault();
|
||||
|
@ -636,13 +636,18 @@ namespace FreeSql.Internal.CommonProvider
|
||||
foreach (var item in list)
|
||||
setListValue(item, null);
|
||||
|
||||
var subSelect = _orm.Select<TNavigate>().DisableGlobalFilter().WithConnection(_connection).WithTransaction(_transaction).TrackToList(_trackToList) as Select1Provider<TNavigate>;
|
||||
var subSelect = _orm.Select<TNavigate>()
|
||||
.DisableGlobalFilter()
|
||||
.WithConnection(_connection)
|
||||
.WithTransaction(_transaction)
|
||||
.TrackToList(_trackToList) as Select1Provider<TNavigate>;
|
||||
if (_tableRules?.Any() == true)
|
||||
foreach (var tr in _tableRules) subSelect.AsTable(tr);
|
||||
|
||||
if (_whereCascadeExpression.Any())
|
||||
subSelect._whereCascadeExpression.AddRange(_whereCascadeExpression.ToArray());
|
||||
|
||||
//subSelect._aliasRule = _aliasRule; //把 SqlServer 查询锁传递下去
|
||||
then?.Invoke(subSelect);
|
||||
var subSelectT1Alias = subSelect._tables[0].Alias;
|
||||
var oldWhere = subSelect._where.ToString();
|
||||
|
Reference in New Issue
Block a user