mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
FreeSql.DbContext 融合 Repository + UnitOfWork
This commit is contained in:
parent
496750da94
commit
a7e06843a9
@ -13,8 +13,9 @@ namespace FreeSql {
|
|||||||
internal IFreeSql _orm;
|
internal IFreeSql _orm;
|
||||||
internal IFreeSql _fsql => _orm ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
|
internal IFreeSql _fsql => _orm ?? throw new ArgumentNullException("请在 OnConfiguring 或 AddFreeDbContext 中配置 UseFreeSql");
|
||||||
|
|
||||||
UnitOfWork _uowPriv;
|
IUnitOfWork _uowPriv;
|
||||||
internal UnitOfWork _uow => _uowPriv ?? (_uowPriv = new UnitOfWork(_fsql));
|
internal IUnitOfWork _uow => _isUseUnitOfWork ? (_uowPriv ?? (_uowPriv = new UnitOfWork(_fsql))) : null;
|
||||||
|
internal bool _isUseUnitOfWork = true; //不使用工作单元事务
|
||||||
|
|
||||||
static ConcurrentDictionary<Type, PropertyInfo[]> _dicGetDbSetProps = new ConcurrentDictionary<Type, PropertyInfo[]>();
|
static ConcurrentDictionary<Type, PropertyInfo[]> _dicGetDbSetProps = new ConcurrentDictionary<Type, PropertyInfo[]>();
|
||||||
protected DbContext() {
|
protected DbContext() {
|
||||||
@ -41,15 +42,14 @@ namespace FreeSql {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Dictionary<Type, object> _dicSet = new Dictionary<Type, object>();
|
protected Dictionary<Type, object> _dicSet = new Dictionary<Type, object>();
|
||||||
public DbSet<TEntity> Set<TEntity>() where TEntity : class => this.Set(typeof(TEntity)) as DbSet<TEntity>;
|
public DbSet<TEntity> Set<TEntity>() where TEntity : class => this.Set(typeof(TEntity)) as DbSet<TEntity>;
|
||||||
public object Set(Type entityType) {
|
public virtual object Set(Type entityType) {
|
||||||
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
|
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
|
||||||
var sd = Activator.CreateInstance(typeof(BaseDbSet<>).MakeGenericType(entityType), this);
|
var sd = Activator.CreateInstance(typeof(DbContextDbSet<>).MakeGenericType(entityType), this);
|
||||||
_dicSet.Add(entityType, sd);
|
_dicSet.Add(entityType, sd);
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Dictionary<string, object> AllSets { get; } = new Dictionary<string, object>();
|
protected Dictionary<string, object> AllSets { get; } = new Dictionary<string, object>();
|
||||||
|
|
||||||
internal class ExecCommandInfo {
|
internal class ExecCommandInfo {
|
||||||
@ -60,7 +60,7 @@ namespace FreeSql {
|
|||||||
}
|
}
|
||||||
internal enum ExecCommandInfoType { Insert, Update, Delete }
|
internal enum ExecCommandInfoType { Insert, Update, Delete }
|
||||||
Queue<ExecCommandInfo> _actions = new Queue<ExecCommandInfo>();
|
Queue<ExecCommandInfo> _actions = new Queue<ExecCommandInfo>();
|
||||||
internal long _affrows = 0;
|
internal int _affrows = 0;
|
||||||
|
|
||||||
internal void EnqueueAction(ExecCommandInfoType actionType, object dbSet, Type stateType, object state) {
|
internal void EnqueueAction(ExecCommandInfoType actionType, object dbSet, Type stateType, object state) {
|
||||||
_actions.Enqueue(new ExecCommandInfo { actionType = actionType, dbSet = dbSet, stateType = stateType, state = state });
|
_actions.Enqueue(new ExecCommandInfo { actionType = actionType, dbSet = dbSet, stateType = stateType, state = state });
|
||||||
@ -73,7 +73,11 @@ namespace FreeSql {
|
|||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
if (_isdisposed) return;
|
if (_isdisposed) return;
|
||||||
try {
|
try {
|
||||||
_uow.Rollback();
|
_actions.Clear();
|
||||||
|
_dicSet.Clear();
|
||||||
|
AllSets.Clear();
|
||||||
|
|
||||||
|
_uow?.Rollback();
|
||||||
} finally {
|
} finally {
|
||||||
_isdisposed = true;
|
_isdisposed = true;
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
@ -11,14 +11,17 @@ using System.Threading.Tasks;
|
|||||||
namespace FreeSql {
|
namespace FreeSql {
|
||||||
partial class DbContext {
|
partial class DbContext {
|
||||||
|
|
||||||
async public Task<long> SaveChangesAsync() {
|
async public Task<int> SaveChangesAsync() {
|
||||||
await ExecCommandAsync();
|
await ExecCommandAsync();
|
||||||
_uow.Commit();
|
_uow?.Commit();
|
||||||
return _affrows;
|
var ret = _affrows;
|
||||||
|
_affrows = 0;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>> _dicExecCommandDbContextBetchAsync = new Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>>();
|
static Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>> _dicExecCommandDbContextBetchAsync = new Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>>();
|
||||||
async internal Task ExecCommandAsync() {
|
async internal Task ExecCommandAsync() {
|
||||||
|
if (_actions.Any() == false) return;
|
||||||
ExecCommandInfo oldinfo = null;
|
ExecCommandInfo oldinfo = null;
|
||||||
var states = new List<object>();
|
var states = new List<object>();
|
||||||
|
|
||||||
|
@ -10,14 +10,17 @@ using System.Linq.Expressions;
|
|||||||
namespace FreeSql {
|
namespace FreeSql {
|
||||||
partial class DbContext {
|
partial class DbContext {
|
||||||
|
|
||||||
public long SaveChanges() {
|
public int SaveChanges() {
|
||||||
ExecCommand();
|
ExecCommand();
|
||||||
_uow.Commit();
|
_uow?.Commit();
|
||||||
return _affrows;
|
var ret = _affrows;
|
||||||
|
_affrows = 0;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dictionary<Type, Dictionary<string, Func<object, object[], int>>> _dicExecCommandDbContextBetch = new Dictionary<Type, Dictionary<string, Func<object, object[], int>>>();
|
static Dictionary<Type, Dictionary<string, Func<object, object[], int>>> _dicExecCommandDbContextBetch = new Dictionary<Type, Dictionary<string, Func<object, object[], int>>>();
|
||||||
internal void ExecCommand() {
|
internal void ExecCommand() {
|
||||||
|
if (_actions.Any() == false) return;
|
||||||
ExecCommandInfo oldinfo = null;
|
ExecCommandInfo oldinfo = null;
|
||||||
var states = new List<object>();
|
var states = new List<object>();
|
||||||
|
|
||||||
|
@ -7,29 +7,41 @@ using System.Linq.Expressions;
|
|||||||
|
|
||||||
namespace FreeSql {
|
namespace FreeSql {
|
||||||
|
|
||||||
internal class BaseDbSet<TEntity> : DbSet<TEntity> where TEntity : class {
|
internal class DbContextDbSet<TEntity> : DbSet<TEntity> where TEntity : class {
|
||||||
|
|
||||||
public BaseDbSet(DbContext ctx) {
|
public DbContextDbSet(DbContext ctx) {
|
||||||
if (ctx != null) {
|
|
||||||
_ctx = ctx;
|
_ctx = ctx;
|
||||||
_uow = ctx._uow;
|
_uow = ctx._uow;
|
||||||
_fsql = ctx._fsql;
|
_fsql = ctx._fsql;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public abstract partial class DbSet<TEntity> where TEntity : class {
|
public abstract partial class DbSet<TEntity> : IDisposable where TEntity : class {
|
||||||
|
|
||||||
internal DbContext _ctx;
|
internal DbContext _ctx;
|
||||||
internal UnitOfWork _uow;
|
internal IUnitOfWork _uow;
|
||||||
internal IFreeSql _fsql;
|
internal IFreeSql _fsql;
|
||||||
bool IsNoneDbContext => _ctx == null;
|
|
||||||
|
|
||||||
protected virtual ISelect<TEntity> OrmSelect(object dywhere) {
|
protected virtual ISelect<TEntity> OrmSelect(object dywhere) {
|
||||||
DbContextExecCommand(); //查询前先提交,否则会出脏读
|
DbContextExecCommand(); //查询前先提交,否则会出脏读
|
||||||
return _fsql.Select<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList);
|
return _fsql.Select<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction(false)).TrackToList(TrackToList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~DbSet() {
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
bool _isdisposed = false;
|
||||||
|
public void Dispose() {
|
||||||
|
if (_isdisposed) return;
|
||||||
|
try {
|
||||||
|
this._dicUpdateTimes.Clear();
|
||||||
|
this._states.Clear();
|
||||||
|
} finally {
|
||||||
|
_isdisposed = true;
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual IInsert<TEntity> OrmInsert() => _fsql.Insert<TEntity>().WithTransaction(_uow?.GetOrBeginTransaction());
|
protected virtual IInsert<TEntity> OrmInsert() => _fsql.Insert<TEntity>().WithTransaction(_uow?.GetOrBeginTransaction());
|
||||||
protected virtual IInsert<TEntity> OrmInsert(TEntity data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
protected virtual IInsert<TEntity> OrmInsert(TEntity data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||||
protected virtual IInsert<TEntity> OrmInsert(IEnumerable<TEntity> data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
protected virtual IInsert<TEntity> OrmInsert(IEnumerable<TEntity> data) => _fsql.Insert<TEntity>(data).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||||
@ -38,11 +50,9 @@ namespace FreeSql {
|
|||||||
protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _fsql.Delete<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction());
|
protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _fsql.Delete<TEntity>(dywhere).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||||
|
|
||||||
internal void EnqueueToDbContext(DbContext.ExecCommandInfoType actionType, EntityState state) {
|
internal void EnqueueToDbContext(DbContext.ExecCommandInfoType actionType, EntityState state) {
|
||||||
if (IsNoneDbContext == false)
|
|
||||||
_ctx.EnqueueAction(actionType, this, typeof(EntityState), state);
|
_ctx.EnqueueAction(actionType, this, typeof(EntityState), state);
|
||||||
}
|
}
|
||||||
internal void IncrAffrows(long affrows) {
|
internal void IncrAffrows(int affrows) {
|
||||||
if (IsNoneDbContext == false)
|
|
||||||
_ctx._affrows += affrows;
|
_ctx._affrows += affrows;
|
||||||
}
|
}
|
||||||
internal void TrackToList(object list) {
|
internal void TrackToList(object list) {
|
||||||
|
@ -8,12 +8,9 @@ namespace FreeSql {
|
|||||||
partial class DbSet<TEntity> {
|
partial class DbSet<TEntity> {
|
||||||
|
|
||||||
Task DbContextExecCommandAsync() {
|
Task DbContextExecCommandAsync() {
|
||||||
if (IsNoneDbContext == false) {
|
|
||||||
_dicUpdateTimes.Clear();
|
_dicUpdateTimes.Clear();
|
||||||
return _ctx.ExecCommandAsync();
|
return _ctx.ExecCommandAsync();
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<int> DbContextBetchAddAsync(EntityState[] adds) {
|
async Task<int> DbContextBetchAddAsync(EntityState[] adds) {
|
||||||
if (adds.Any() == false) return 0;
|
if (adds.Any() == false) return 0;
|
||||||
@ -59,9 +56,6 @@ namespace FreeSql {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsNoneDbContext)
|
|
||||||
IncrAffrows(await OrmInsert(data).ExecuteAffrowsAsync());
|
|
||||||
else
|
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,9 +88,6 @@ namespace FreeSql {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsNoneDbContext)
|
|
||||||
IncrAffrows(await OrmInsert(data).ExecuteAffrowsAsync());
|
|
||||||
else
|
|
||||||
//进入队列,等待 SaveChanges 时执行
|
//进入队列,等待 SaveChanges 时执行
|
||||||
foreach (var s in data)
|
foreach (var s in data)
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
||||||
@ -154,56 +145,6 @@ namespace FreeSql {
|
|||||||
//等待下次对比再保存
|
//等待下次对比再保存
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<int> UpdateAffrowsAsync(TEntity data) => UpdateRangeAffrowsAsync(new[] { data });
|
|
||||||
async internal Task<int> UpdateRangeAffrowsAsync(IEnumerable<TEntity> data) {
|
|
||||||
if (CanUpdate(data, true) == false) return 0;
|
|
||||||
if (IsNoneDbContext) {
|
|
||||||
var dataarray = data.ToArray();
|
|
||||||
var ups = new List<EntityState>();
|
|
||||||
var totalAffrows = 0;
|
|
||||||
for (var a = 0; a < dataarray.Length + 1; a++) {
|
|
||||||
var item = a < dataarray.Length ? dataarray[a] : null;
|
|
||||||
if (item != null) {
|
|
||||||
var state = CreateEntityState(item);
|
|
||||||
state.Value = item;
|
|
||||||
ups.Add(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
var affrows = await DbContextBetchUpdatePrivAsync(ups.ToArray(), item == null);
|
|
||||||
if (affrows == -999) { //最后一个元素已被删除
|
|
||||||
ups.RemoveAt(ups.Count - 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (affrows == -998 || affrows == -997) { //没有执行更新
|
|
||||||
var laststate = ups[ups.Count - 1];
|
|
||||||
ups.Clear();
|
|
||||||
if (affrows == -997) ups.Add(laststate); //保留最后一个
|
|
||||||
}
|
|
||||||
if (affrows > 0) {
|
|
||||||
totalAffrows += affrows;
|
|
||||||
var islastNotUpdated = ups.Count != affrows;
|
|
||||||
var laststate = ups[ups.Count - 1];
|
|
||||||
ups.Clear();
|
|
||||||
if (islastNotUpdated) ups.Add(laststate); //保留最后一个
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncrAffrows(totalAffrows);
|
|
||||||
return totalAffrows;
|
|
||||||
}
|
|
||||||
foreach (var item in data) {
|
|
||||||
if (_dicUpdateTimes.ContainsKey(item))
|
|
||||||
await DbContextExecCommandAsync();
|
|
||||||
_dicUpdateTimes.Add(item, 1);
|
|
||||||
|
|
||||||
var state = CreateEntityState(item);
|
|
||||||
state.OldValue = item;
|
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
internal Task UpdateAsync(TEntity data) => UpdateAffrowsAsync(data);
|
|
||||||
internal Task UpdateRangeAsync(IEnumerable<TEntity> data) => UpdateRangeAffrowsAsync(data);
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region RemoveAsync
|
#region RemoveAsync
|
||||||
@ -212,28 +153,6 @@ namespace FreeSql {
|
|||||||
var affrows = await this.OrmDelete(dels.Select(a => a.Value)).ExecuteAffrowsAsync();
|
var affrows = await this.OrmDelete(dels.Select(a => a.Value)).ExecuteAffrowsAsync();
|
||||||
return Math.Max(dels.Length, affrows);
|
return Math.Max(dels.Length, affrows);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<int> RemoveAffrowsAsync(TEntity data) => RemoveRangeAffrowsAsync(new[] { data });
|
|
||||||
async internal Task<int> RemoveRangeAffrowsAsync(IEnumerable<TEntity> data) {
|
|
||||||
if (CanRemove(data, true) == false) return 0;
|
|
||||||
var dels = new List<EntityState>();
|
|
||||||
foreach (var item in data) {
|
|
||||||
var state = CreateEntityState(item);
|
|
||||||
if (_states.ContainsKey(state.Key)) _states.Remove(state.Key);
|
|
||||||
_fsql.ClearEntityPrimaryValueWithIdentityAndGuid(item);
|
|
||||||
|
|
||||||
if (IsNoneDbContext) dels.Add(state);
|
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
|
||||||
}
|
|
||||||
if (IsNoneDbContext) {
|
|
||||||
var affrows = await DbContextBetchRemoveAsync(dels.ToArray());
|
|
||||||
IncrAffrows(affrows);
|
|
||||||
return affrows;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
internal Task RemoveAsync(TEntity data) => RemoveAffrowsAsync(data);
|
|
||||||
internal Task RemoveRangeAsync(IEnumerable<TEntity> data) => RemoveRangeAffrowsAsync(data);
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,9 @@ namespace FreeSql {
|
|||||||
partial class DbSet<TEntity> {
|
partial class DbSet<TEntity> {
|
||||||
|
|
||||||
void DbContextExecCommand() {
|
void DbContextExecCommand() {
|
||||||
if (IsNoneDbContext == false) {
|
|
||||||
_dicUpdateTimes.Clear();
|
_dicUpdateTimes.Clear();
|
||||||
_ctx.ExecCommand();
|
_ctx.ExecCommand();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int DbContextBetchAdd(EntityState[] adds) {
|
int DbContextBetchAdd(EntityState[] adds) {
|
||||||
if (adds.Any() == false) return 0;
|
if (adds.Any() == false) return 0;
|
||||||
@ -56,13 +54,9 @@ namespace FreeSql {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
if (IsNoneDbContext)
|
|
||||||
IncrAffrows(OrmInsert(data).ExecuteAffrows());
|
|
||||||
else
|
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public void Add(TEntity data) => AddPriv(data, true);
|
public void Add(TEntity data) => AddPriv(data, true);
|
||||||
public void AddRange(IEnumerable<TEntity> data) {
|
public void AddRange(IEnumerable<TEntity> data) {
|
||||||
if (CanAdd(data, true) == false) return;
|
if (CanAdd(data, true) == false) return;
|
||||||
@ -92,9 +86,6 @@ namespace FreeSql {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsNoneDbContext)
|
|
||||||
IncrAffrows(OrmInsert(data).ExecuteAffrows());
|
|
||||||
else
|
|
||||||
//进入队列,等待 SaveChanges 时执行
|
//进入队列,等待 SaveChanges 时执行
|
||||||
foreach (var s in data)
|
foreach (var s in data)
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(s));
|
||||||
@ -154,42 +145,9 @@ namespace FreeSql {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<TEntity, byte> _dicUpdateTimes = new Dictionary<TEntity, byte>();
|
Dictionary<TEntity, byte> _dicUpdateTimes = new Dictionary<TEntity, byte>();
|
||||||
internal int UpdateAffrows(TEntity data) => UpdateRangeAffrows(new[] { data });
|
public void Update(TEntity data) => UpdateRange(new[] { data });
|
||||||
internal int UpdateRangeAffrows(IEnumerable<TEntity> data) {
|
public void UpdateRange(IEnumerable<TEntity> data) {
|
||||||
if (CanUpdate(data, true) == false) return 0;
|
if (CanUpdate(data, true) == false) return;
|
||||||
if (IsNoneDbContext) {
|
|
||||||
var dataarray = data.ToArray();
|
|
||||||
var ups = new List<EntityState>();
|
|
||||||
var totalAffrows = 0;
|
|
||||||
for (var a = 0; a < dataarray.Length + 1; a++) {
|
|
||||||
var item = a < dataarray.Length ? dataarray[a] : null;
|
|
||||||
if (item != null) {
|
|
||||||
var state = CreateEntityState(item);
|
|
||||||
state.Value = item;
|
|
||||||
ups.Add(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
var affrows = DbContextBetchUpdatePriv(ups.ToArray(), item == null);
|
|
||||||
if (affrows == -999) { //最后一个元素已被删除
|
|
||||||
ups.RemoveAt(ups.Count - 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (affrows == -998 || affrows == -997) { //没有执行更新
|
|
||||||
var laststate = ups[ups.Count - 1];
|
|
||||||
ups.Clear();
|
|
||||||
if (affrows == -997) ups.Add(laststate); //保留最后一个
|
|
||||||
}
|
|
||||||
if (affrows > 0) {
|
|
||||||
totalAffrows += affrows;
|
|
||||||
var islastNotUpdated = ups.Count != affrows;
|
|
||||||
var laststate = ups[ups.Count - 1];
|
|
||||||
ups.Clear();
|
|
||||||
if (islastNotUpdated) ups.Add(laststate); //保留最后一个
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncrAffrows(totalAffrows);
|
|
||||||
return totalAffrows;
|
|
||||||
}
|
|
||||||
foreach (var item in data) {
|
foreach (var item in data) {
|
||||||
if (_dicUpdateTimes.ContainsKey(item))
|
if (_dicUpdateTimes.ContainsKey(item))
|
||||||
DbContextExecCommand();
|
DbContextExecCommand();
|
||||||
@ -199,10 +157,7 @@ namespace FreeSql {
|
|||||||
state.OldValue = item;
|
state.OldValue = item;
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
public void Update(TEntity data) => UpdateAffrows(data);
|
|
||||||
public void UpdateRange(IEnumerable<TEntity> data) => UpdateRangeAffrows(data);
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Remove
|
#region Remove
|
||||||
@ -212,27 +167,17 @@ namespace FreeSql {
|
|||||||
return Math.Max(dels.Length, affrows);
|
return Math.Max(dels.Length, affrows);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int RemoveAffrows(TEntity data) => RemoveRangeAffrows(new[] { data });
|
public void Remove(TEntity data) => RemoveRange(new[] { data });
|
||||||
internal int RemoveRangeAffrows(IEnumerable<TEntity> data) {
|
public void RemoveRange(IEnumerable<TEntity> data) {
|
||||||
if (CanRemove(data, true) == false) return 0;
|
if (CanRemove(data, true) == false) return;
|
||||||
var dels = new List<EntityState>();
|
|
||||||
foreach (var item in data) {
|
foreach (var item in data) {
|
||||||
var state = CreateEntityState(item);
|
var state = CreateEntityState(item);
|
||||||
if (_states.ContainsKey(state.Key)) _states.Remove(state.Key);
|
if (_states.ContainsKey(state.Key)) _states.Remove(state.Key);
|
||||||
_fsql.ClearEntityPrimaryValueWithIdentityAndGuid(item);
|
_fsql.ClearEntityPrimaryValueWithIdentityAndGuid(item);
|
||||||
|
|
||||||
if (IsNoneDbContext) dels.Add(state);
|
|
||||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
||||||
}
|
}
|
||||||
if (IsNoneDbContext) {
|
|
||||||
var affrows = DbContextBetchRemove(dels.ToArray());
|
|
||||||
IncrAffrows(affrows);
|
|
||||||
return affrows;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
public void Remove(TEntity data) => RemoveAffrows(data);
|
|
||||||
public void RemoveRange(IEnumerable<TEntity> data) => RemoveRangeAffrows(data);
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FreeSql {
|
||||||
|
internal class RepositoryDbContext<TEntity> : DbContext where TEntity : class {
|
||||||
|
|
||||||
|
protected BaseRepository<TEntity> _repos;
|
||||||
|
public RepositoryDbContext(IFreeSql orm, BaseRepository<TEntity> repos) : base() {
|
||||||
|
_orm = orm;
|
||||||
|
_repos = repos;
|
||||||
|
_isUseUnitOfWork = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object Set(Type entityType) {
|
||||||
|
if (_dicSet.ContainsKey(entityType)) return _dicSet[entityType];
|
||||||
|
var sd = Activator.CreateInstance(typeof(RepositoryDbSet<>).MakeGenericType(entityType), _repos);
|
||||||
|
_dicSet.Add(entityType, sd);
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
RepositoryDbSet<TEntity> _dbSet;
|
||||||
|
public RepositoryDbSet<TEntity> DbSet => _dbSet ?? (_dbSet = Set<TEntity>() as RepositoryDbSet<TEntity>);
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,9 @@ namespace FreeSql {
|
|||||||
|
|
||||||
protected BaseRepository<TEntity> _repos;
|
protected BaseRepository<TEntity> _repos;
|
||||||
public RepositoryDbSet(BaseRepository<TEntity> repos) {
|
public RepositoryDbSet(BaseRepository<TEntity> repos) {
|
||||||
|
_ctx = repos._db;
|
||||||
_fsql = repos._fsql;
|
_fsql = repos._fsql;
|
||||||
_uow = repos._uow;
|
_uow = repos.UnitOfWork;
|
||||||
_repos = repos;
|
_repos = repos;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FreeSql {
|
||||||
|
|
||||||
|
public interface IRepositoryUnitOfWork : IUnitOfWork {
|
||||||
|
/// <summary>
|
||||||
|
/// 在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <param name="filter">数据过滤 + 验证</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在工作单元内创建仓库类,工作单元下的仓储操作具有事务特点
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
|
/// <param name="filter">数据过滤 + 验证</param>
|
||||||
|
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RepositoryUnitOfWork : UnitOfWork, IRepositoryUnitOfWork {
|
||||||
|
|
||||||
|
public RepositoryUnitOfWork(IFreeSql fsql) : base(fsql) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class {
|
||||||
|
var repos = new GuidRepository<TEntity>(_fsql, filter, asTable);
|
||||||
|
repos.UnitOfWork = this;
|
||||||
|
return repos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class {
|
||||||
|
var repos = new DefaultRepository<TEntity, TKey>(_fsql, filter);
|
||||||
|
repos.UnitOfWork = this;
|
||||||
|
return repos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ public static class FreeSqlRepositoryExtenssions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回仓库类,适用 Insert 方法无须返回插入的数据
|
/// 返回仓库类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
/// <param name="that"></param>
|
/// <param name="that"></param>
|
||||||
|
@ -11,9 +11,7 @@ namespace FreeSql {
|
|||||||
where TEntity : class {
|
where TEntity : class {
|
||||||
|
|
||||||
internal IFreeSql _fsql;
|
internal IFreeSql _fsql;
|
||||||
internal UnitOfWork _uow;
|
internal RepositoryDbContext<TEntity> _db;
|
||||||
RepositoryDbSet<TEntity> _setPriv;
|
|
||||||
internal RepositoryDbSet<TEntity> _set => _setPriv ?? (_setPriv = new RepositoryDbSet<TEntity>(this));
|
|
||||||
public IDataFilter<TEntity> DataFilter { get; } = new DataFilter<TEntity>();
|
public IDataFilter<TEntity> DataFilter { get; } = new DataFilter<TEntity>();
|
||||||
Func<string, string> _asTableVal;
|
Func<string, string> _asTableVal;
|
||||||
protected Func<string, string> AsTable {
|
protected Func<string, string> AsTable {
|
||||||
@ -32,45 +30,89 @@ namespace FreeSql {
|
|||||||
DataFilterUtil.SetRepositoryDataFilter(this, null);
|
DataFilterUtil.SetRepositoryDataFilter(this, null);
|
||||||
DataFilter.Apply("", filter);
|
DataFilter.Apply("", filter);
|
||||||
AsTable = asTable;
|
AsTable = asTable;
|
||||||
|
_db = new RepositoryDbContext<TEntity>(_fsql, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type EntityType => _set._entityTypeInternal;
|
~BaseRepository() {
|
||||||
public IUpdate<TEntity> UpdateDiy => _set.OrmUpdateInternal(null);
|
this.Dispose();
|
||||||
|
}
|
||||||
|
bool _isdisposed = false;
|
||||||
|
public void Dispose() {
|
||||||
|
if (_isdisposed) return;
|
||||||
|
try {
|
||||||
|
_db.Dispose();
|
||||||
|
this.DataFilter.Dispose();
|
||||||
|
} finally {
|
||||||
|
_isdisposed = true;
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUnitOfWork UnitOfWork { get; set; }
|
||||||
|
public Type EntityType => _db.DbSet._entityTypeInternal;
|
||||||
|
public IUpdate<TEntity> UpdateDiy => _db.DbSet.OrmUpdateInternal(null);
|
||||||
|
|
||||||
public ISelect<TEntity> Select => _set.OrmSelectInternal(null);
|
public ISelect<TEntity> Select => _db.DbSet.OrmSelectInternal(null);
|
||||||
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _set.OrmSelectInternal(null).Where(exp);
|
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _db.DbSet.OrmSelectInternal(null).Where(exp);
|
||||||
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _set.OrmSelectInternal(null).WhereIf(condition, exp);
|
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _db.DbSet.OrmSelectInternal(null).WhereIf(condition, exp);
|
||||||
|
|
||||||
public int Delete(Expression<Func<TEntity, bool>> predicate) => _set.OrmDeleteInternal(null).Where(predicate).ExecuteAffrows();
|
public int Delete(Expression<Func<TEntity, bool>> predicate) => _db.DbSet.OrmDeleteInternal(null).Where(predicate).ExecuteAffrows();
|
||||||
public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _set.OrmDeleteInternal(null).Where(predicate).ExecuteAffrowsAsync();
|
public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _db.DbSet.OrmDeleteInternal(null).Where(predicate).ExecuteAffrowsAsync();
|
||||||
|
|
||||||
public int Delete(TEntity entity) => _set.RemoveAffrows(entity);
|
public int Delete(TEntity entity) {
|
||||||
public Task<int> DeleteAsync(TEntity entity) => _set.RemoveAffrowsAsync(entity);
|
_db.DbSet.Remove(entity);
|
||||||
public int Delete(IEnumerable<TEntity> entitys) => _set.RemoveRangeAffrows(entitys);
|
return _db.SaveChanges();
|
||||||
public Task<int> DeleteAsync(IEnumerable<TEntity> entitys) => _set.RemoveRangeAffrowsAsync(entitys);
|
}
|
||||||
|
public Task<int> DeleteAsync(TEntity entity) {
|
||||||
|
_db.DbSet.Remove(entity);
|
||||||
|
return _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
public int Delete(IEnumerable<TEntity> entitys) {
|
||||||
|
_db.DbSet.RemoveRange(entitys);
|
||||||
|
return _db.SaveChanges();
|
||||||
|
}
|
||||||
|
public Task<int> DeleteAsync(IEnumerable<TEntity> entitys) {
|
||||||
|
_db.DbSet.RemoveRange(entitys);
|
||||||
|
return _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public virtual TEntity Insert(TEntity entity) {
|
public virtual TEntity Insert(TEntity entity) {
|
||||||
_set.Add(entity);
|
_db.DbSet.Add(entity);
|
||||||
|
_db.SaveChanges();
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
async public virtual Task<TEntity> InsertAsync(TEntity entity) {
|
||||||
|
await _db.DbSet.AddAsync(entity);
|
||||||
|
_db.SaveChanges();
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
public virtual List<TEntity> Insert(IEnumerable<TEntity> entitys) {
|
public virtual List<TEntity> Insert(IEnumerable<TEntity> entitys) {
|
||||||
_set.AddRange(entitys);
|
_db.DbSet.AddRange(entitys);
|
||||||
|
_db.SaveChanges();
|
||||||
return entitys.ToList();
|
return entitys.ToList();
|
||||||
}
|
}
|
||||||
async public virtual Task<TEntity> InsertAsync(TEntity entity) {
|
|
||||||
await _set.AddAsync(entity);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
async public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys) {
|
async public virtual Task<List<TEntity>> InsertAsync(IEnumerable<TEntity> entitys) {
|
||||||
await _set.AddRangeAsync(entitys);
|
await _db.DbSet.AddRangeAsync(entitys);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
return entitys.ToList();
|
return entitys.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Update(TEntity entity) => _set.UpdateAffrows(entity);
|
public int Update(TEntity entity) {
|
||||||
public Task<int> UpdateAsync(TEntity entity) => _set.UpdateAffrowsAsync(entity);
|
_db.DbSet.Update(entity);
|
||||||
public int Update(IEnumerable<TEntity> entitys) => _set.UpdateRangeAffrows(entitys);
|
return _db.SaveChanges();
|
||||||
public Task<int> UpdateAsync(IEnumerable<TEntity> entitys) => _set.UpdateRangeAffrowsAsync(entitys);
|
}
|
||||||
|
public Task<int> UpdateAsync(TEntity entity) {
|
||||||
|
_db.DbSet.Update(entity);
|
||||||
|
return _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
public int Update(IEnumerable<TEntity> entitys) {
|
||||||
|
_db.DbSet.UpdateRange(entitys);
|
||||||
|
return _db.SaveChanges();
|
||||||
|
}
|
||||||
|
public Task<int> UpdateAsync(IEnumerable<TEntity> entitys) {
|
||||||
|
_db.DbSet.UpdateRange(entitys);
|
||||||
|
return _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IRepository<TEntity, TKey>
|
public abstract class BaseRepository<TEntity, TKey> : BaseRepository<TEntity>, IRepository<TEntity, TKey>
|
||||||
@ -81,17 +123,19 @@ namespace FreeSql {
|
|||||||
|
|
||||||
public int Delete(TKey id) {
|
public int Delete(TKey id) {
|
||||||
var stateKey = string.Concat(id);
|
var stateKey = string.Concat(id);
|
||||||
if (_set._statesInternal.ContainsKey(stateKey)) _set._statesInternal.Remove(stateKey);
|
if (_db.DbSet._statesInternal.ContainsKey(stateKey))
|
||||||
return _set.OrmDeleteInternal(id).ExecuteAffrows();
|
_db.DbSet._statesInternal.Remove(stateKey);
|
||||||
|
return _db.DbSet.OrmDeleteInternal(id).ExecuteAffrows();
|
||||||
}
|
}
|
||||||
public Task<int> DeleteAsync(TKey id) {
|
public Task<int> DeleteAsync(TKey id) {
|
||||||
var stateKey = string.Concat(id);
|
var stateKey = string.Concat(id);
|
||||||
if (_set._statesInternal.ContainsKey(stateKey)) _set._statesInternal.Remove(stateKey);
|
if (_db.DbSet._statesInternal.ContainsKey(stateKey))
|
||||||
return _set.OrmDeleteInternal(id).ExecuteAffrowsAsync();
|
_db.DbSet._statesInternal.Remove(stateKey);
|
||||||
|
return _db.DbSet.OrmDeleteInternal(id).ExecuteAffrowsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TEntity Find(TKey id) => _set.OrmSelectInternal(id).ToOne();
|
public TEntity Find(TKey id) => _db.DbSet.OrmSelectInternal(id).ToOne();
|
||||||
public Task<TEntity> FindAsync(TKey id) => _set.OrmSelectInternal(id).ToOneAsync();
|
public Task<TEntity> FindAsync(TKey id) => _db.DbSet.OrmSelectInternal(id).ToOneAsync();
|
||||||
|
|
||||||
public TEntity Get(TKey id) => Find(id);
|
public TEntity Get(TKey id) => Find(id);
|
||||||
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
||||||
|
@ -4,8 +4,9 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace FreeSql {
|
namespace FreeSql {
|
||||||
|
|
||||||
public interface IRepository {
|
public interface IRepository : IDisposable {
|
||||||
Type EntityType { get; }
|
Type EntityType { get; }
|
||||||
|
IUnitOfWork UnitOfWork { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRepository<TEntity> : IReadOnlyRepository<TEntity>, IBasicRepository<TEntity>
|
public interface IRepository<TEntity> : IReadOnlyRepository<TEntity>, IBasicRepository<TEntity>
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace FreeSql {
|
|
||||||
class RepositoryUnitOfWork : UnitOfWork, IRepositoryUnitOfWork {
|
|
||||||
|
|
||||||
public RepositoryUnitOfWork(IFreeSql fsql) : base(fsql) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class {
|
|
||||||
var repos = new GuidRepository<TEntity>(_fsql, filter, asTable);
|
|
||||||
repos._uow = this;
|
|
||||||
return repos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class {
|
|
||||||
var repos = new DefaultRepository<TEntity, TKey>(_fsql, filter);
|
|
||||||
repos._uow = this;
|
|
||||||
return repos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FreeSql {
|
namespace FreeSql {
|
||||||
public interface IUnitOfWork : IDisposable {
|
public interface IUnitOfWork : IDisposable {
|
||||||
|
|
||||||
|
DbTransaction GetOrBeginTransaction(bool isCreate = true);
|
||||||
|
|
||||||
void Commit();
|
void Commit();
|
||||||
|
|
||||||
void Rollback();
|
void Rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRepositoryUnitOfWork : IUnitOfWork {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 在工作单元内创建默认仓库类,工作单元下的仓储操作具有事务特点
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
|
||||||
/// <typeparam name="TKey"></typeparam>
|
|
||||||
/// <param name="filter">数据过滤 + 验证</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
DefaultRepository<TEntity, TKey> GetRepository<TEntity, TKey>(Expression<Func<TEntity, bool>> filter = null) where TEntity : class;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 在工作单元内创建仓库类,适用 Insert 方法无须返回插入的数据,工作单元下的仓储操作具有事务特点
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TEntity"></typeparam>
|
|
||||||
/// <param name="filter">数据过滤 + 验证</param>
|
|
||||||
/// <param name="asTable">分表规则,参数:旧表名;返回:新表名 https://github.com/2881099/FreeSql/wiki/Repository</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
GuidRepository<TEntity> GetGuidRepository<TEntity>(Expression<Func<TEntity, bool>> filter = null, Func<string, string> asTable = null) where TEntity : class;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace FreeSql {
|
|||||||
_tran = null;
|
_tran = null;
|
||||||
_conn = null;
|
_conn = null;
|
||||||
}
|
}
|
||||||
internal DbTransaction GetOrBeginTransaction(bool isCreate = true) {
|
public DbTransaction GetOrBeginTransaction(bool isCreate = true) {
|
||||||
|
|
||||||
if (_tran != null) return _tran;
|
if (_tran != null) return _tran;
|
||||||
if (isCreate == false) return null;
|
if (isCreate == false) return null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user