mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-18 20:08:15 +08:00
- 增加 FreeSql.DbContext 实体对象的变化事件;
> 文档:https://github.com/2881099/FreeSql/wiki/DbContext#%E5%AE%9E%E4%BD%93%E5%8F%98%E5%8C%96%E4%BA%8B%E4%BB%B6 - 补充 Aop.CurdBefore 事件参数 Table 实体类型的元数据;
This commit is contained in:
@ -38,11 +38,20 @@ namespace FreeSql
|
||||
{
|
||||
_optionsPriv = new DbContextOptions();
|
||||
if (FreeSqlDbContextExtensions._dicSetDbContextOptions.TryGetValue(Orm, out var opt))
|
||||
{
|
||||
_optionsPriv.EnableAddOrUpdateNavigateList = opt.EnableAddOrUpdateNavigateList;
|
||||
_optionsPriv.OnEntityChange = opt.OnEntityChange;
|
||||
}
|
||||
}
|
||||
return _optionsPriv;
|
||||
}
|
||||
}
|
||||
internal void EmitOnEntityChange(List<DbContext.EntityChangeInfo> report)
|
||||
{
|
||||
var oec = UnitOfWork?.OnEntityChange ?? Options.OnEntityChange;
|
||||
if (oec == null || report == null || report.Any() == false) return;
|
||||
oec(report);
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected DbContext()
|
||||
@ -146,20 +155,26 @@ namespace FreeSql
|
||||
#endregion
|
||||
|
||||
#region Queue Action
|
||||
internal List<EntityChangeInfo> _entityChangeReport = new List<EntityChangeInfo>();
|
||||
public class EntityChangeInfo
|
||||
{
|
||||
public object Object { get; set; }
|
||||
public EntityChangeType Type { get; set; }
|
||||
}
|
||||
public enum EntityChangeType { Insert, Update, Delete, SqlRaw }
|
||||
internal class ExecCommandInfo
|
||||
{
|
||||
public ExecCommandInfoType actionType { get; set; }
|
||||
public EntityChangeType changeType { get; set; }
|
||||
public IDbSet dbSet { get; set; }
|
||||
public Type stateType { get; set; }
|
||||
public Type entityType { get; set; }
|
||||
public object state { get; set; }
|
||||
}
|
||||
internal enum ExecCommandInfoType { Insert, Update, Delete }
|
||||
Queue<ExecCommandInfo> _actions = new Queue<ExecCommandInfo>();
|
||||
internal int _affrows = 0;
|
||||
|
||||
internal void EnqueueAction(ExecCommandInfoType actionType, IDbSet dbSet, Type stateType, Type entityType, object state) =>
|
||||
_actions.Enqueue(new ExecCommandInfo { actionType = actionType, dbSet = dbSet, stateType = stateType, entityType = entityType, state = state });
|
||||
internal void EnqueueAction(EntityChangeType changeType, IDbSet dbSet, Type stateType, Type entityType, object state) =>
|
||||
_actions.Enqueue(new ExecCommandInfo { changeType = changeType, dbSet = dbSet, stateType = stateType, entityType = entityType, state = state });
|
||||
#endregion
|
||||
|
||||
~DbContext() => this.Dispose();
|
||||
|
@ -13,10 +13,7 @@ namespace FreeSql
|
||||
async public virtual Task<int> SaveChangesAsync()
|
||||
{
|
||||
await ExecCommandAsync();
|
||||
UnitOfWork?.Commit();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
return SaveChangesSuccess();
|
||||
}
|
||||
|
||||
static Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>> _dicExecCommandDbContextBetchAsync = new Dictionary<Type, Dictionary<string, Func<object, object[], Task<int>>>>();
|
||||
@ -96,31 +93,31 @@ namespace FreeSql
|
||||
var isLiveUpdate = false;
|
||||
|
||||
if (_actions.Any() == false && states.Any() ||
|
||||
info != null && oldinfo.actionType != info.actionType ||
|
||||
info != null && oldinfo.changeType != info.changeType ||
|
||||
info != null && oldinfo.stateType != info.stateType ||
|
||||
info != null && oldinfo.entityType != info.entityType)
|
||||
{
|
||||
|
||||
if (info != null && oldinfo.actionType == info.actionType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType)
|
||||
if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType)
|
||||
{
|
||||
//最后一个,合起来发送
|
||||
states.Add(info.state);
|
||||
info = null;
|
||||
}
|
||||
|
||||
switch (oldinfo.actionType)
|
||||
switch (oldinfo.changeType)
|
||||
{
|
||||
case ExecCommandInfoType.Insert:
|
||||
case EntityChangeType.Insert:
|
||||
await funcInsert();
|
||||
break;
|
||||
case ExecCommandInfoType.Delete:
|
||||
case EntityChangeType.Delete:
|
||||
await funcDelete();
|
||||
break;
|
||||
}
|
||||
isLiveUpdate = true;
|
||||
}
|
||||
|
||||
if (isLiveUpdate || oldinfo.actionType == ExecCommandInfoType.Update)
|
||||
if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update)
|
||||
{
|
||||
if (states.Any())
|
||||
await funcUpdate(isLiveUpdate);
|
||||
|
@ -1,4 +1,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace FreeSql
|
||||
{
|
||||
public class DbContextOptions
|
||||
@ -17,5 +21,10 @@ namespace FreeSql
|
||||
/// - 属性集合不为空时,与数据库存在的关联数据(中间表)完全对比,计算出应该删除和添加的记录
|
||||
/// </summary>
|
||||
public bool EnableAddOrUpdateNavigateList { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 实体变化事件
|
||||
/// </summary>
|
||||
public Action<List<DbContext.EntityChangeInfo>> OnEntityChange { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,26 @@ namespace FreeSql
|
||||
{
|
||||
partial class DbContext
|
||||
{
|
||||
|
||||
int SaveChangesSuccess()
|
||||
{
|
||||
UnitOfWork?.Commit();
|
||||
int ret;
|
||||
try
|
||||
{
|
||||
EmitOnEntityChange(_entityChangeReport);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_entityChangeReport.Clear();
|
||||
ret = _affrows;
|
||||
_affrows = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public virtual int SaveChanges()
|
||||
{
|
||||
ExecCommand();
|
||||
UnitOfWork?.Commit();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
return SaveChangesSuccess();
|
||||
}
|
||||
|
||||
static Dictionary<Type, Dictionary<string, Func<object, object[], int>>> _dicExecCommandDbContextBetch = new Dictionary<Type, Dictionary<string, Func<object, object[], int>>>();
|
||||
@ -96,31 +108,31 @@ namespace FreeSql
|
||||
var isLiveUpdate = false;
|
||||
|
||||
if (_actions.Any() == false && states.Any() ||
|
||||
info != null && oldinfo.actionType != info.actionType ||
|
||||
info != null && oldinfo.changeType != info.changeType ||
|
||||
info != null && oldinfo.stateType != info.stateType ||
|
||||
info != null && oldinfo.entityType != info.entityType)
|
||||
{
|
||||
|
||||
if (info != null && oldinfo.actionType == info.actionType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType)
|
||||
if (info != null && oldinfo.changeType == info.changeType && oldinfo.stateType == info.stateType && oldinfo.entityType == info.entityType)
|
||||
{
|
||||
//最后一个,合起来发送
|
||||
states.Add(info.state);
|
||||
info = null;
|
||||
}
|
||||
|
||||
switch (oldinfo.actionType)
|
||||
switch (oldinfo.changeType)
|
||||
{
|
||||
case ExecCommandInfoType.Insert:
|
||||
case EntityChangeType.Insert:
|
||||
funcInsert();
|
||||
break;
|
||||
case ExecCommandInfoType.Delete:
|
||||
case EntityChangeType.Delete:
|
||||
funcDelete();
|
||||
break;
|
||||
}
|
||||
isLiveUpdate = true;
|
||||
}
|
||||
|
||||
if (isLiveUpdate || oldinfo.actionType == ExecCommandInfoType.Update)
|
||||
if (isLiveUpdate || oldinfo.changeType == EntityChangeType.Update)
|
||||
{
|
||||
if (states.Any())
|
||||
funcUpdate(isLiveUpdate);
|
||||
|
@ -59,8 +59,8 @@ namespace FreeSql
|
||||
protected virtual IUpdate<TEntity> OrmUpdate(IEnumerable<TEntity> entitys) => _db.Orm.Update<TEntity>().AsType(_entityType).SetSource(entitys).WithTransaction(_uow?.GetOrBeginTransaction());
|
||||
protected virtual IDelete<TEntity> OrmDelete(object dywhere) => _db.Orm.Delete<TEntity>().AsType(_entityType).WithTransaction(_uow?.GetOrBeginTransaction()).WhereDynamic(dywhere);
|
||||
|
||||
internal void EnqueueToDbContext(DbContext.ExecCommandInfoType actionType, EntityState state) =>
|
||||
_db.EnqueueAction(actionType, this, typeof(EntityState), _entityType, state);
|
||||
internal void EnqueueToDbContext(DbContext.EntityChangeType changeType, EntityState state) =>
|
||||
_db.EnqueueAction(changeType, this, typeof(EntityState), _entityType, state);
|
||||
|
||||
internal void IncrAffrows(int affrows) =>
|
||||
_db._affrows += affrows;
|
||||
|
@ -23,6 +23,7 @@ namespace FreeSql
|
||||
{
|
||||
if (adds.Any() == false) return 0;
|
||||
var affrows = await this.OrmInsert(adds.Select(a => a.Value)).ExecuteAffrowsAsync();
|
||||
_db._entityChangeReport.AddRange(adds.Select(a => new DbContext.EntityChangeInfo { Object = a.Value, Type = DbContext.EntityChangeType.Insert }));
|
||||
return affrows;
|
||||
}
|
||||
|
||||
@ -45,6 +46,7 @@ namespace FreeSql
|
||||
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
|
||||
IncrAffrows(1);
|
||||
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
await AddOrUpdateNavigateListAsync(data, true);
|
||||
@ -53,6 +55,7 @@ namespace FreeSql
|
||||
{
|
||||
await DbContextExecCommandAsync();
|
||||
var newval = (await this.OrmInsert(data).ExecuteInsertedAsync()).First();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert });
|
||||
IncrAffrows(1);
|
||||
_db.Orm.MapEntityValue(_entityType, newval, data);
|
||||
Attach(newval);
|
||||
@ -67,6 +70,7 @@ namespace FreeSql
|
||||
var idtval = await this.OrmInsert(data).ExecuteIdentityAsync();
|
||||
IncrAffrows(1);
|
||||
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
await AddOrUpdateNavigateListAsync(data, true);
|
||||
@ -74,7 +78,7 @@ namespace FreeSql
|
||||
return;
|
||||
}
|
||||
}
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(data));
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
await AddOrUpdateNavigateListAsync(data, true);
|
||||
@ -100,6 +104,7 @@ namespace FreeSql
|
||||
await DbContextExecCommandAsync();
|
||||
var rets = await this.OrmInsert(data).ExecuteInsertedAsync();
|
||||
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.Orm.Ado.DataType} 的返回数据,与添加的数目不匹配");
|
||||
_db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert }));
|
||||
var idx = 0;
|
||||
foreach (var s in data)
|
||||
_db.Orm.MapEntityValue(_entityType, rets[idx++], s);
|
||||
@ -119,7 +124,7 @@ namespace FreeSql
|
||||
{
|
||||
//进入队列,等待 SaveChanges 时执行
|
||||
foreach (var item in data)
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(item));
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(item));
|
||||
AttachRange(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
foreach (var item in data)
|
||||
@ -193,7 +198,9 @@ namespace FreeSql
|
||||
{
|
||||
var delall = _db.Orm.Delete<object>().AsType(tref.RefMiddleEntityType);
|
||||
foreach (var midWhere in midWheres) delall.Where(midWhere);
|
||||
var sql = delall.ToSql();
|
||||
await delall.ExecuteAffrowsAsync();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = sql, Type = DbContext.EntityChangeType.SqlRaw });
|
||||
}
|
||||
else //保存
|
||||
{
|
||||
@ -314,6 +321,7 @@ namespace FreeSql
|
||||
var update = this.OrmUpdate(null).SetSource(updateSource).IgnoreColumns(cuig);
|
||||
|
||||
var affrows = await update.ExecuteAffrowsAsync();
|
||||
_db._entityChangeReport.AddRange(updateSource.Select(a => new DbContext.EntityChangeInfo { Object = a, Type = DbContext.EntityChangeType.Update }));
|
||||
|
||||
foreach (var newval in data)
|
||||
{
|
||||
@ -352,7 +360,7 @@ namespace FreeSql
|
||||
|
||||
var state = CreateEntityState(item);
|
||||
state.OldValue = item;
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Update, state);
|
||||
}
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
foreach (var item in data)
|
||||
@ -365,6 +373,7 @@ namespace FreeSql
|
||||
{
|
||||
if (dels.Any() == false) return 0;
|
||||
var affrows = await this.OrmDelete(dels.Select(a => a.Value)).ExecuteAffrowsAsync();
|
||||
_db._entityChangeReport.AddRange(dels.Select(a => new DbContext.EntityChangeInfo { Object = a.Value, Type = DbContext.EntityChangeType.Delete }));
|
||||
return Math.Max(dels.Length, affrows);
|
||||
}
|
||||
#endregion
|
||||
|
@ -23,6 +23,7 @@ namespace FreeSql
|
||||
{
|
||||
if (adds.Any() == false) return 0;
|
||||
var affrows = this.OrmInsert(adds.Select(a => a.Value)).ExecuteAffrows();
|
||||
_db._entityChangeReport.AddRange(adds.Select(a => new DbContext.EntityChangeInfo { Object = a.Value, Type = DbContext.EntityChangeType.Insert }));
|
||||
return affrows;
|
||||
}
|
||||
|
||||
@ -45,6 +46,7 @@ namespace FreeSql
|
||||
var idtval = this.OrmInsert(data).ExecuteIdentity();
|
||||
IncrAffrows(1);
|
||||
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
AddOrUpdateNavigateList(data, true);
|
||||
@ -53,6 +55,7 @@ namespace FreeSql
|
||||
{
|
||||
DbContextExecCommand();
|
||||
var newval = this.OrmInsert(data).ExecuteInserted().First();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = newval, Type = DbContext.EntityChangeType.Insert });
|
||||
IncrAffrows(1);
|
||||
_db.Orm.MapEntityValue(_entityType, newval, data);
|
||||
Attach(newval);
|
||||
@ -67,6 +70,7 @@ namespace FreeSql
|
||||
var idtval = this.OrmInsert(data).ExecuteIdentity();
|
||||
IncrAffrows(1);
|
||||
_db.Orm.SetEntityIdentityValueWithPrimary(_entityType, data, idtval);
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = data, Type = DbContext.EntityChangeType.Insert });
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
AddOrUpdateNavigateList(data, true);
|
||||
@ -74,7 +78,7 @@ namespace FreeSql
|
||||
return;
|
||||
}
|
||||
}
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(data));
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(data));
|
||||
Attach(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
AddOrUpdateNavigateList(data, true);
|
||||
@ -104,6 +108,7 @@ namespace FreeSql
|
||||
DbContextExecCommand();
|
||||
var rets = this.OrmInsert(data).ExecuteInserted();
|
||||
if (rets.Count != data.Count()) throw new Exception($"特别错误:批量添加失败,{_db.Orm.Ado.DataType} 的返回数据,与添加的数目不匹配");
|
||||
_db._entityChangeReport.AddRange(rets.Select(a => new DbContext.EntityChangeInfo { Object = a, Type = DbContext.EntityChangeType.Insert }));
|
||||
var idx = 0;
|
||||
foreach (var s in data)
|
||||
_db.Orm.MapEntityValue(_entityType, rets[idx++], s);
|
||||
@ -123,7 +128,7 @@ namespace FreeSql
|
||||
{
|
||||
//进入队列,等待 SaveChanges 时执行
|
||||
foreach (var item in data)
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Insert, CreateEntityState(item));
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Insert, CreateEntityState(item));
|
||||
AttachRange(data);
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
foreach (var item in data)
|
||||
@ -203,7 +208,9 @@ namespace FreeSql
|
||||
{
|
||||
var delall = _db.Orm.Delete<object>().AsType(tref.RefMiddleEntityType);
|
||||
foreach (var midWhere in midWheres) delall.Where(midWhere);
|
||||
var sql = delall.ToSql();
|
||||
delall.ExecuteAffrows();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = sql, Type = DbContext.EntityChangeType.SqlRaw });
|
||||
}
|
||||
else //保存
|
||||
{
|
||||
@ -324,6 +331,7 @@ namespace FreeSql
|
||||
var update = this.OrmUpdate(null).SetSource(updateSource).IgnoreColumns(cuig);
|
||||
|
||||
var affrows = update.ExecuteAffrows();
|
||||
_db._entityChangeReport.AddRange(updateSource.Select(a => new DbContext.EntityChangeInfo { Object = a, Type = DbContext.EntityChangeType.Update }));
|
||||
|
||||
foreach (var newval in data)
|
||||
{
|
||||
@ -368,7 +376,7 @@ namespace FreeSql
|
||||
|
||||
var state = CreateEntityState(item);
|
||||
state.OldValue = item;
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Update, state);
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Update, state);
|
||||
}
|
||||
if (_db.Options.EnableAddOrUpdateNavigateList)
|
||||
foreach (var item in data)
|
||||
@ -381,6 +389,7 @@ namespace FreeSql
|
||||
{
|
||||
if (dels.Any() == false) return 0;
|
||||
var affrows = this.OrmDelete(dels.Select(a => a.Value)).ExecuteAffrows();
|
||||
_db._entityChangeReport.AddRange(dels.Select(a => new DbContext.EntityChangeInfo { Object = a.Value, Type = DbContext.EntityChangeType.Delete }));
|
||||
return Math.Max(dels.Length, affrows);
|
||||
}
|
||||
|
||||
@ -398,7 +407,7 @@ namespace FreeSql
|
||||
_states.TryRemove(state.Key, out var trystate);
|
||||
_db.Orm.ClearEntityPrimaryValueWithIdentityAndGuid(_entityType, item);
|
||||
|
||||
EnqueueToDbContext(DbContext.ExecCommandInfoType.Delete, state);
|
||||
EnqueueToDbContext(DbContext.EntityChangeType.Delete, state);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
@ -1,6 +1,7 @@
|
||||
using FreeSql;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public static class FreeSqlDbContextExtensions
|
||||
{
|
||||
@ -31,12 +32,13 @@ public static class FreeSqlDbContextExtensions
|
||||
/// </summary>
|
||||
/// <param name="that"></param>
|
||||
/// <param name="options"></param>
|
||||
public static void SetDbContextOptions(this IFreeSql that, Action<DbContextOptions> options)
|
||||
public static IFreeSql SetDbContextOptions(this IFreeSql that, Action<DbContextOptions> options)
|
||||
{
|
||||
if (options == null) return;
|
||||
if (options == null) return that;
|
||||
var cfg = _dicSetDbContextOptions.GetOrAdd(that, t => new DbContextOptions());
|
||||
options(cfg);
|
||||
_dicSetDbContextOptions.AddOrUpdate(that, cfg, (t, o) => cfg);
|
||||
return that;
|
||||
}
|
||||
internal static ConcurrentDictionary<IFreeSql, DbContextOptions> _dicSetDbContextOptions = new ConcurrentDictionary<IFreeSql, DbContextOptions>();
|
||||
}
|
@ -60,6 +60,11 @@
|
||||
- 属性集合不为空时,与数据库存在的关联数据(中间表)完全对比,计算出应该删除和添加的记录
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.DbContextOptions.OnEntityChange">
|
||||
<summary>
|
||||
实体变化事件
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSql.DbSet`1.AsType(System.Type)">
|
||||
<summary>
|
||||
动态Type,在使用 DbSet<object> 后使用本方法,指定实体类型
|
||||
@ -214,6 +219,16 @@
|
||||
开启工作单元
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.IUnitOfWork.OnEntityChange">
|
||||
<summary>
|
||||
实体变化事件
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.UnitOfWork.EntityChangeReport">
|
||||
<summary>
|
||||
工作单元的实体变化记录
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:FreeSqlDbContextExtensions.CreateDbContext(IFreeSql)">
|
||||
<summary>
|
||||
创建普通数据上下文档对象
|
||||
|
@ -54,19 +54,39 @@ namespace FreeSql
|
||||
});
|
||||
}
|
||||
|
||||
int SaveChangesSuccess()
|
||||
{
|
||||
int ret;
|
||||
try
|
||||
{
|
||||
if (UnitOfWork == null) EmitOnEntityChange(_entityChangeReport);
|
||||
else
|
||||
{
|
||||
var uow = UnitOfWork as UnitOfWork;
|
||||
if (uow != null)
|
||||
{
|
||||
uow.EntityChangeReport.AddRange(_entityChangeReport);
|
||||
if (uow.OnEntityChange == null) uow.OnEntityChange = Options.OnEntityChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_entityChangeReport.Clear();
|
||||
ret = _affrows;
|
||||
_affrows = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public override int SaveChanges()
|
||||
{
|
||||
ExecCommand();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
return SaveChangesSuccess();
|
||||
}
|
||||
async public override Task<int> SaveChangesAsync()
|
||||
{
|
||||
await ExecCommandAsync();
|
||||
var ret = _affrows;
|
||||
_affrows = 0;
|
||||
return ret;
|
||||
return SaveChangesSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using FreeSql.Extensions.EntityUtil;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
@ -69,8 +70,22 @@ namespace FreeSql
|
||||
public ISelect<TEntity> Where(Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).Where(exp);
|
||||
public ISelect<TEntity> WhereIf(bool condition, Expression<Func<TEntity, bool>> exp) => _dbset.OrmSelectInternal(null).WhereIf(condition, exp);
|
||||
|
||||
public int Delete(Expression<Func<TEntity, bool>> predicate) => _dbset.OrmDeleteInternal(null).Where(predicate).ExecuteAffrows();
|
||||
public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate) => _dbset.OrmDeleteInternal(null).Where(predicate).ExecuteAffrowsAsync();
|
||||
public int Delete(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
||||
var sql = delete.ToSql();
|
||||
var affrows = delete.ExecuteAffrows();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = sql, Type = DbContext.EntityChangeType.SqlRaw });
|
||||
return affrows;
|
||||
}
|
||||
async public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
var delete = _dbset.OrmDeleteInternal(null).Where(predicate);
|
||||
var sql = delete.ToSql();
|
||||
var affrows = await delete.ExecuteAffrowsAsync();
|
||||
_db._entityChangeReport.Add(new DbContext.EntityChangeInfo { Object = sql, Type = DbContext.EntityChangeType.SqlRaw });
|
||||
return affrows;
|
||||
}
|
||||
|
||||
public int Delete(TEntity entity)
|
||||
{
|
||||
@ -170,21 +185,23 @@ namespace FreeSql
|
||||
{
|
||||
}
|
||||
|
||||
public int Delete(TKey id)
|
||||
TEntity CheckTKeyAndReturnIdEntity(TKey id)
|
||||
{
|
||||
var stateKey = string.Concat(id);
|
||||
_dbset._statesInternal.TryRemove(stateKey, out var trystate);
|
||||
return _dbset.OrmDeleteInternal(id).ExecuteAffrows();
|
||||
}
|
||||
public Task<int> DeleteAsync(TKey id)
|
||||
{
|
||||
var stateKey = string.Concat(id);
|
||||
_dbset._statesInternal.TryRemove(stateKey, out var trystate);
|
||||
return _dbset.OrmDeleteInternal(id).ExecuteAffrowsAsync();
|
||||
var tb = _db.Orm.CodeFirst.GetTableByEntity(EntityType);
|
||||
if (tb.Primarys.Length != 1) throw new Exception($"实体类型 {EntityType.Name} 主键数量不为 1,无法使用该方法");
|
||||
if (tb.Primarys[0].CsType.NullableTypeOrThis() != typeof(TKey).NullableTypeOrThis()) throw new Exception($"实体类型 {EntityType.Name} 主键类型不为 {typeof(TKey).FullName},无法使用该方法");
|
||||
var obj = Activator.CreateInstance(tb.Type);
|
||||
_db.Orm.SetEntityValueWithPropertyName(tb.Type, obj, tb.Primarys[0].CsName, id);
|
||||
var ret = obj as TEntity;
|
||||
if (ret == null) throw new Exception($"实体类型 {EntityType.Name} 无法转换为 {typeof(TEntity).Name},无法使用该方法");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public TEntity Find(TKey id) => _dbset.OrmSelectInternal(id).ToOne();
|
||||
public Task<TEntity> FindAsync(TKey id) => _dbset.OrmSelectInternal(id).ToOneAsync();
|
||||
public int Delete(TKey id) => Delete(CheckTKeyAndReturnIdEntity(id));
|
||||
public Task<int> DeleteAsync(TKey id) => DeleteAsync(CheckTKeyAndReturnIdEntity(id));
|
||||
|
||||
public TEntity Find(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOne();
|
||||
public Task<TEntity> FindAsync(TKey id) => _dbset.OrmSelectInternal(CheckTKeyAndReturnIdEntity(id)).ToOneAsync();
|
||||
|
||||
public TEntity Get(TKey id) => Find(id);
|
||||
public Task<TEntity> GetAsync(TKey id) => FindAsync(id);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
|
||||
@ -32,5 +33,10 @@ namespace FreeSql
|
||||
/// 开启工作单元
|
||||
/// </summary>
|
||||
void Open();
|
||||
|
||||
/// <summary>
|
||||
/// 实体变化事件
|
||||
/// </summary>
|
||||
Action<List<DbContext.EntityChangeInfo>> OnEntityChange { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using SafeObjectPool;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Threading;
|
||||
@ -32,6 +33,7 @@ namespace FreeSql
|
||||
#if ns20
|
||||
Current.Value = null;
|
||||
#endif
|
||||
EntityChangeReport.Clear();
|
||||
}
|
||||
|
||||
public bool Enable { get; private set; } = true;
|
||||
@ -76,7 +78,11 @@ namespace FreeSql
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_tran != null) _tran.Commit();
|
||||
if (_tran != null)
|
||||
{
|
||||
_tran.Commit();
|
||||
OnEntityChange?.Invoke(EntityChangeReport);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -94,6 +100,13 @@ namespace FreeSql
|
||||
ReturnObject();
|
||||
}
|
||||
}
|
||||
|
||||
public Action<List<DbContext.EntityChangeInfo>> OnEntityChange { get; set; }
|
||||
/// <summary>
|
||||
/// 工作单元的实体变化记录
|
||||
/// </summary>
|
||||
public List<DbContext.EntityChangeInfo> EntityChangeReport { get; } = new List<DbContext.EntityChangeInfo>();
|
||||
|
||||
~UnitOfWork()
|
||||
{
|
||||
this.Dispose();
|
||||
|
Reference in New Issue
Block a user