/// <summary> /// 单表增删改,列表中的实体类型相同 /// </summary> /// <param name="p_list"></param> /// <param name="p_isNotify"></param> /// <returns></returns> static async Task <bool> BatchSaveSameType(IList p_list, bool p_isNotify) { var model = EntitySchema.Get(p_list.GetType().GetGenericArguments()[0]); if (model.OnSaving != null) { foreach (var item in p_list) { if (item != null && !await OnSaving(model, item)) { return(false); } } } var dts = model.Schema.GetBatchSaveSql(p_list); // 不需要保存 if (dts == null || dts.Count == 0) { if (p_isNotify) { Kit.Msg(_unchangedMsg); } return(false); } if (await BatchExec(dts) > 0) { if (p_list is Table tbl) { tbl.AcceptChanges(); } else { foreach (var row in p_list.OfType <Row>()) { if (row.IsChanged || row.IsAdded) { row.AcceptChanges(); } } } if (p_isNotify) { Kit.Msg("保存成功!"); } return(true); } if (p_isNotify) { Kit.Warn("保存失败!"); } return(false); }
/// <summary> /// 返回所有实体列表 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <returns></returns> public static Task <Table <TEntity> > GetAll <TEntity>() where TEntity : Entity { return(new UnaryRpc( typeof(TSvc).Name, "Da.Query", EntitySchema.Get(typeof(TEntity)).Schema.GetSelectAllSql(), null ).Call <Table <TEntity> >()); }
/// <summary> /// 根据主键删除实体对象,仅支持单主键id,依靠数据库的级联删除自动删除子实体 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_id">主键</param> /// <param name="p_isNotify">是否提示删除结果</param> /// <returns>true 删除成功</returns> public static async Task <bool> DelByID <TEntity>(long p_id, bool p_isNotify = true) { var model = EntitySchema.Get(typeof(TEntity)); bool suc = await Exec(model.Schema.SqlDelete, new { id = p_id }) == 1; if (p_isNotify) { Kit.Msg(suc ? "删除成功!" : "删除失败!"); } return(suc); }
/// <summary> /// 获取实体类型的定义 /// </summary> /// <param name="p_type">实体类型</param> /// <returns></returns> public static EntitySchema Get(Type p_type) { if (_models.TryGetValue(p_type, out var m)) { return(m); } var model = new EntitySchema(p_type); _models[p_type] = model; return(model); }
async Task ApplyEventAndCache(Entity p_entity, EntitySchema p_model) { if (p_entity.IsAdded || p_entity.IsChanged) { // 不直接调用GatherSaveEvents,确保事件参数类型准确,不然发布事件时无法类型转换! _gatherSaveEvents.MakeGenericMethod(p_entity.GetType()).Invoke(this, new object[] { p_entity, p_model }); //GatherSaveEvents(p_entity, p_model); p_entity.AcceptChanges(); } if (p_model.CacheHandler != null && !p_entity.IsAdded && p_entity.IsChanged) { await p_model.CacheHandler.Remove(p_entity); } }
/// <summary> /// 单表批量删除 /// </summary> /// <param name="p_list"></param> /// <returns></returns> async Task <int> BatchDeleteSameType(IList p_list) { var model = EntitySchema.Get(p_list.GetType().GetGenericArguments()[0]); if (model.OnDeleting != null) { foreach (var item in p_list) { await(Task) model.OnDeleting.Invoke(item, null); } } Dict dt = model.Schema.GetDeleteSql(p_list); return(await BatchExecDelete(dt, p_list, model)); }
/// <summary> /// 保存实体时收集待发布的领域事件 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_entity"></param> /// <param name="p_model"></param> void GatherSaveEvents <TEntity>(TEntity p_entity, EntitySchema p_model) where TEntity : Entity { var events = p_entity.GetDomainEvents(); if (events != null) { AddDomainEvents(events); } if (p_model.CudEvent != CudEvent.None) { if (p_entity.IsAdded) { if ((p_model.CudEvent & CudEvent.LocalInsert) == CudEvent.LocalInsert) { AddDomainEvent(new DomainEvent(false, new InsertEvent <TEntity> { Entity = p_entity })); } if ((p_model.CudEvent & CudEvent.RemoteInsert) == CudEvent.RemoteInsert) { AddDomainEvent(new DomainEvent(true, new InsertEvent <TEntity> { Entity = p_entity })); } } else if (p_entity.IsChanged) { if ((p_model.CudEvent & CudEvent.LocalUpdate) == CudEvent.LocalUpdate) { AddDomainEvent(new DomainEvent(false, new UpdateEvent <TEntity> { Entity = p_entity })); } if ((p_model.CudEvent & CudEvent.RemoteUpdate) == CudEvent.RemoteUpdate) { AddDomainEvent(new DomainEvent(true, new UpdateEvent <TEntity> { Entity = p_entity })); } } } }
/// <summary> /// 保存实体数据 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_entity">待保存的实体</param> /// <param name="p_isNotify">是否提示保存结果</param> /// <returns>是否成功</returns> public static async Task <bool> Save <TEntity>(TEntity p_entity, bool p_isNotify = true) where TEntity : Entity { if (p_entity == null || (!p_entity.IsAdded && !p_entity.IsChanged)) { if (p_isNotify) { Kit.Warn(_unchangedMsg); } return(false); } var model = EntitySchema.Get(typeof(TEntity)); if (model.OnSaving != null) { // 保存前外部校验,不合格在外部抛出异常 if (!await OnSaving(model, p_entity)) { return(false); } } Dict dt = model.Schema.GetSaveSql(p_entity); int cnt = await Exec((string)dt["text"], (Dict)dt["params"]); if (cnt > 0) { p_entity.AcceptChanges(); if (p_isNotify) { Kit.Msg("保存成功!"); } return(true); } if (p_isNotify) { Kit.Warn("保存失败!"); } return(false); }
/// <summary> /// 多表批量删除 /// </summary> /// <param name="p_list"></param> /// <returns></returns> async Task <int> BatchDeleteMultiTypes(IList p_list) { int cnt = 0; foreach (var item in p_list) { if (item is Entity entity) { var model = EntitySchema.Get(item.GetType()); if (model.OnDeleting != null) { await(Task) model.OnDeleting.Invoke(item, null); } var ls = new List <Row> { entity }; Dict dt = model.Schema.GetDeleteSql(ls); cnt += await BatchExecDelete(dt, ls, model); } else if (item is IList clist && clist.Count > 0) { Type tp = item.GetType(); if (tp.IsGenericType && tp.GetGenericArguments()[0].IsSubclassOf(typeof(Entity))) { // IList<Entity> 或 Table<Entity> var model = EntitySchema.Get(tp.GetGenericArguments()[0]); if (model.OnDeleting != null) { foreach (var ci in clist) { await(Task) model.OnDeleting.Invoke(item, null); } } Dict dt = model.Schema.GetDeleteSql(clist); cnt += await BatchExecDelete(dt, clist, model); } } } return(cnt); }
/// <summary> /// 删除实体,同步删除缓存,依靠数据库的级联删除自动删除子实体 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_entity">待删除的实体</param> /// <returns>true 删除成功</returns> public async Task <bool> Delete <TEntity>(TEntity p_entity) where TEntity : Entity { Throw.IfNull(p_entity, _saveError); var model = EntitySchema.Get(typeof(TEntity)); if (model.OnDeleting != null) { await(Task) model.OnDeleting.Invoke(p_entity, null); } Dict dt = model.Schema.GetDeleteSql(new List <Entity> { p_entity }); return(await BatchExecDelete(dt, new List <Entity> { p_entity }, model) == 1); }
/// <summary> /// 删除前外部校验,不合格在外部抛出异常 /// </summary> /// <param name="p_model"></param> /// <param name="p_entity"></param> /// <returns></returns> static async Task <bool> OnDeleting(EntitySchema p_model, object p_entity) { try { await(Task) p_model.OnDeleting.Invoke(p_entity, null); } catch (Exception ex) { if (ex.InnerException is KnownException kex) { Kit.Warn(kex.Message); } else { Kit.Warn(ex.Message); } return(false); } return(true); }
public ChildEntitySchema(Type p_type, PropertyInfo p_propInfo, string p_parentID) { var tbl = p_type.GetCustomAttribute <TblAttribute>(false); if (tbl == null || string.IsNullOrEmpty(tbl.Name)) { throw new Exception($"实体{p_type.Name}缺少映射表设置!"); } Type = p_type; PropInfo = p_propInfo; ParentID = p_parentID; Schema = EntitySchema.GetTableSchema(tbl.Name); if (Schema.PrimaryKey.Count == 0) { throw new Exception($"实体{p_type.Name}的映射表{Schema.Name}无主键!"); } // sql变量名parentid固定 SqlSelect = $"select * from `{Schema.Name}` where {ParentID}=@parentid"; }
/// <summary> /// 删除实体,依靠数据库的级联删除自动删除子实体 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_entity">待删除的行</param> /// <param name="p_isNotify">是否提示删除结果</param> /// <returns>true 删除成功</returns> public static async Task <bool> Delete <TEntity>(TEntity p_entity, bool p_isNotify = true) where TEntity : Entity { if (p_entity == null || p_entity.IsAdded) { if (p_isNotify) { Kit.Warn(_saveError); } return(false); } var model = EntitySchema.Get(typeof(TEntity)); if (model.OnDeleting != null) { if (!await OnDeleting(model, p_entity)) { return(false); } } Dict dt = model.Schema.GetDeleteSql(new List <Row> { p_entity }); bool suc = await Exec((string)dt["text"], ((List <Dict>)dt["params"])[0]) == 1; if (p_isNotify) { if (suc) { Kit.Msg("删除成功!"); } else { Kit.Warn("删除失败!"); } } return(suc); }
/// <summary> /// 将实体数据传输到服务端,由服务端DataProvider保存实体,用于需要触发领域事件或同步缓存的情况 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_entity">待保存的实体</param> /// <param name="p_isNotify">是否提示保存结果</param> /// <returns>是否成功</returns> public static async Task <bool> SaveBySvc <TEntity>(TEntity p_entity, bool p_isNotify = true) where TEntity : Entity { if (p_entity == null || (!p_entity.IsAdded && !p_entity.IsChanged)) { if (p_isNotify) { Kit.Warn(_unchangedMsg); } return(false); } var model = EntitySchema.Get(typeof(TEntity)); bool suc = await new UnaryRpc( typeof(TSvc).Name, "EntityAccess.Save", p_entity, model.Schema.Name ).Call <bool>(); if (suc) { p_entity.AcceptChanges(); if (p_isNotify) { Kit.Msg("保存成功!"); } return(true); } if (p_isNotify) { Kit.Warn("保存失败!"); } return(false); }
/// <summary> /// 单表增删改,列表中的实体类型相同 /// </summary> /// <param name="p_list"></param> /// <returns></returns> async Task <bool> BatchSaveSameType(IList p_list) { var model = EntitySchema.Get(p_list.GetType().GetGenericArguments()[0]); if (model.OnSaving != null) { foreach (var item in p_list) { await(Task) model.OnSaving.Invoke(item, null); } } var dts = model.Schema.GetBatchSaveSql(p_list); // 不需要保存 if (dts == null || dts.Count == 0) { Throw.Msg(_unchangedMsg); } await BatchExec(dts); // 实体事件、缓存 foreach (var entity in p_list.OfType <Entity>()) { if (entity.IsChanged || entity.IsAdded) { await ApplyEventAndCache(entity, model); } } if (p_list is Table tbl) { tbl.DeletedRows?.Clear(); } return(true); }
/// <summary> /// 单表批量执行,运行sql删除、收集领域事件、同步缓存 /// </summary> /// <param name="p_dt"></param> /// <param name="p_list"></param> /// <param name="p_model"></param> /// <returns></returns> async Task <int> BatchExecDelete(Dict p_dt, IList p_list, EntitySchema p_model) { int cnt = 0; string sql = (string)p_dt["text"]; List <Dict> ls = (List <Dict>)p_dt["params"]; var db = _db; for (int i = 0; i < p_list.Count; i++) { if (await db.Exec(sql, ls[i]) == 1) { cnt++; var entity = p_list[i]; // 删除实体事件,不直接调GatherDelEvents! _gatherDelEvents.MakeGenericMethod(entity.GetType()).Invoke(this, new object[] { entity, p_model }); // 删除缓存 if (p_model.CacheHandler != null) { await p_model.CacheHandler.Remove(entity as Entity); } } } return(cnt); }
/// <summary> /// 根据主键或唯一索引列获得实体对象(包含所有列值),仅支持单主键 /// 不存在时返回null,启用缓存时首先从缓存中获取 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_keyName">主键列名</param> /// <param name="p_keyVal">主键值</param> /// <returns>返回实体对象或null</returns> public async Task <TEntity> GetByKey <TEntity>(string p_keyName, string p_keyVal) where TEntity : Entity { var model = EntitySchema.Get(typeof(TEntity)); TEntity entity = null; if (model.CacheHandler != null) { entity = await model.CacheHandler.Get <TEntity>(p_keyName, p_keyVal); } if (entity == null) { entity = await _db.First <TEntity>( $"select * from `{model.Schema.Name}` where {p_keyName}=@{p_keyName}", new Dict { { p_keyName, p_keyVal } }); if (entity != null && model.CacheHandler != null) { await model.CacheHandler.Cache(entity); } } return(entity); }
/// <summary> /// 返回所有实体列表 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <returns></returns> public Task <Table <TEntity> > GetAll <TEntity>() where TEntity : Entity { return(_db.Query <TEntity>(EntitySchema.Get(typeof(TEntity)).Schema.GetSelectAllSql(), null)); }
/// <summary> /// 多表批量删除 /// </summary> /// <param name="p_list"></param> /// <param name="p_isNotify"></param> /// <returns></returns> static async Task <bool> BatchDeleteMultiTypes(IList p_list, bool p_isNotify) { var dts = new List <Dict>(); foreach (var item in p_list) { if (item is Entity entity) { var model = EntitySchema.Get(item.GetType()); if (model.OnDeleting != null) { if (!await OnDeleting(model, entity)) { return(false); } } dts.Add(model.Schema.GetDeleteSql(new List <Row> { entity })); } else if (item is IList clist && clist.Count > 0) { Type tp = item.GetType(); if (tp.IsGenericType && tp.GetGenericArguments()[0].IsSubclassOf(typeof(Entity))) { // IList<Entity> 或 Table<Entity> var model = EntitySchema.Get(tp.GetGenericArguments()[0]); if (model.OnDeleting != null) { foreach (var ci in clist) { if (!await OnDeleting(model, ci)) { return(false); } } } dts.Add(model.Schema.GetDeleteSql(clist)); } } } // 不需要删除 if (dts == null || dts.Count == 0) { if (p_isNotify) { Kit.Msg(_unchangedMsg); } return(true); } bool suc = await BatchExec(dts) > 0; if (p_isNotify) { if (suc) { Kit.Msg("删除成功!"); } else { Kit.Warn("删除失败!"); } } return(suc); }
/// <summary> /// 多表增删改 /// </summary> /// <param name="p_list"></param> /// <returns></returns> async Task <bool> BatchSaveMultiTypes(IList p_list) { var dts = new List <Dict>(); foreach (var item in p_list) { if (item is Entity entity) { if (entity.IsAdded || entity.IsChanged) { var model = EntitySchema.Get(item.GetType()); if (model.OnSaving != null) { await(Task) model.OnSaving.Invoke(entity, null); } dts.Add(model.Schema.GetSaveSql(entity)); } } else if (item is IList clist) { // 不判断列表项数0,因可能Table<Entity>只包含删除列表的情况! Type tp = item.GetType(); if (tp.IsGenericType && tp.GetGenericArguments()[0].IsSubclassOf(typeof(Entity))) { // IList<Entity> 或 Table<Entity> var model = EntitySchema.Get(tp.GetGenericArguments()[0]); if (model.OnSaving != null) { foreach (var ci in clist) { await(Task) model.OnSaving.Invoke(ci, null); } } var cdts = model.Schema.GetBatchSaveSql(clist); if (cdts != null && cdts.Count > 0) { dts.AddRange(cdts); } } } } // 不需要保存 if (dts == null || dts.Count == 0) { Throw.Msg(_unchangedMsg); } await BatchExec(dts); foreach (var item in p_list) { if (item is Entity entity) { if (entity.IsChanged || entity.IsAdded) { await ApplyEventAndCache(entity, EntitySchema.Get(item.GetType())); } } else if (item is IList clist && clist.Count > 0) { Type tp = item.GetType(); if (tp.IsGenericType && tp.GetGenericArguments()[0].IsSubclassOf(typeof(Entity))) { // IList<Entity> 或 Table<Entity> var model = EntitySchema.Get(tp.GetGenericArguments()[0]); foreach (var row in clist.OfType <Entity>()) { if (row.IsAdded || row.IsChanged) { await ApplyEventAndCache(row, model); } } if (item is Table tbl) { tbl.DeletedRows?.Clear(); } } } } return(true); }
/// <summary> /// 多表增删改 /// </summary> /// <param name="p_list"></param> /// <param name="p_isNotify"></param> /// <returns></returns> static async Task <bool> BatchSaveMultiTypes(IList p_list, bool p_isNotify) { var dts = new List <Dict>(); foreach (var item in p_list) { if (item is Entity entity) { if (entity.IsAdded || entity.IsChanged) { var model = EntitySchema.Get(item.GetType()); if (model.OnSaving != null) { if (!await OnSaving(model, entity)) { return(false); } } dts.Add(model.Schema.GetSaveSql(entity)); } } else if (item is IList clist) { // 不判断列表项数0,因可能Table<Entity>只包含删除列表的情况! Type tp = item.GetType(); if (tp.IsGenericType && tp.GetGenericArguments()[0].IsSubclassOf(typeof(Entity))) { // IList<Entity> 或 Table<Entity> var model = EntitySchema.Get(tp.GetGenericArguments()[0]); if (model.OnSaving != null) { foreach (var ci in clist) { if (!await OnSaving(model, ci)) { return(false); } } } var cdts = model.Schema.GetBatchSaveSql(clist); if (cdts != null && cdts.Count > 0) { dts.AddRange(cdts); } } } } // 不需要保存 if (dts == null || dts.Count == 0) { if (p_isNotify) { Kit.Msg(_unchangedMsg); } return(true); } bool suc = await BatchExec(dts) > 0; if (suc) { foreach (var item in p_list) { if (item is Entity entity) { entity.AcceptChanges(); } else if (item is Table tbl) { tbl.AcceptChanges(); tbl.DeletedRows?.Clear(); } else if (item is IList clist && clist.Count > 0) { foreach (var ci in clist) { if (ci is Row row && (row.IsAdded || row.IsChanged)) { row.AcceptChanges(); } } } } if (p_isNotify) { Kit.Msg("保存成功!"); } return(true); } if (p_isNotify) { Kit.Warn("保存失败!"); } return(false); }
/// <summary> /// 根据主键获得实体对象(包含所有列值),仅支持单主键id,不存在时返回null /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="p_id">主键</param> /// <returns>返回实体对象或null</returns> public static Task <TEntity> GetByID <TEntity>(long p_id) where TEntity : Entity { return(First <TEntity>(EntitySchema.Get(typeof(TEntity)).Schema.SqlSelect, new { id = p_id })); }