Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
 /// <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> >());
 }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        /// <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));
        }
Beispiel #7
0
        /// <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
                        }));
                    }
                }
            }
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
 /// <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);
 }
Beispiel #12
0
        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";
        }
Beispiel #13
0
        /// <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);
        }
Beispiel #14
0
        /// <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);
        }
Beispiel #15
0
        /// <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);
        }
Beispiel #16
0
        /// <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);
        }
Beispiel #17
0
        /// <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);
        }
Beispiel #18
0
 /// <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));
 }
Beispiel #19
0
        /// <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);
        }
Beispiel #20
0
        /// <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);
        }
Beispiel #21
0
        /// <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);
        }
Beispiel #22
0
 /// <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 }));
 }