private async Task SendEventNotifyForUpdateAsync(bool nameUpdated, GroupInput input)
        {
            var groupNameUpdatedNotify = nameUpdated
                ? new EventNotifyDto
            {
                Target         = NotifyTargetType.Conversation,
                TargetId       = input.Id.ToString(),
                Created        = DateTimeOffset.UtcNow,
                Text           = input.Name,
                TargetCategory = (int)GroupEventNotifyType.GroupNameUpdated
            }
                : null;

            var participantAddedNotify = (input.AddingMemberNames?.Count > 0)
                ? new EventNotifyDto
            {
                Target         = NotifyTargetType.Conversation,
                TargetId       = input.Id.ToString(),
                Created        = DateTimeOffset.UtcNow,
                Text           = string.Join(",", input.AddingMemberNames),
                TargetCategory = (int)GroupEventNotifyType.ParticipantAdded
            }
                : null;

            var participantRemovedNotify = (input.RemovingMemberNames?.Count > 0)
                ? new EventNotifyDto
            {
                Target         = NotifyTargetType.Conversation,
                TargetId       = input.Id.ToString(),
                Created        = DateTimeOffset.UtcNow,
                Text           = string.Join(",", input.RemovingMemberNames),
                TargetCategory = (int)GroupEventNotifyType.ParticipantRemoved
            }
                : null;

            var notifies = new List <EventNotifyDto>();

            if (groupNameUpdatedNotify != null)
            {
                notifies.Add(groupNameUpdatedNotify);
            }
            if (participantAddedNotify != null)
            {
                notifies.Add(participantAddedNotify);
            }
            if (participantRemovedNotify != null)
            {
                notifies.Add(participantAddedNotify);
            }

            if (notifies.Count > 0)
            {
                await _busMs.Publish(new GroupNotified { Id = input.Id.Value, Notifies = notifies });
            }
        }
        public async Task <Guid> CreateCustomAsync(GroupInput input)
        {
            if (string.IsNullOrWhiteSpace(input.Name))
            {
                throw new ArgumentNullException("must not be null", nameof(input.Name));
            }

            if (input.CurrentUserId == Guid.Empty)
            {
                throw new ArgumentNullException("must not be empty", nameof(input.CurrentUserId));
            }

            if (!input.CurrentEmployeeId.HasValue)
            {
                throw new ArgumentNullException("must not be null", nameof(input.CurrentEmployeeId));
            }

            using (var db = new ServiceDbContext(_dbOptions))
            {
                using (var tx = db.Database.BeginTransaction())
                {
                    try
                    {
                        var entity = _mapper.Map <Group>(input);
                        entity.Type = GroupType.CustomChat;
                        db.Groups.Add(entity);

                        await db.SaveChangesAsync();

                        await _busMs.Publish(new GroupAdded
                        {
                            Id = entity.Id
                        });

                        tx.Commit();
                        return(entity.Id);
                    }
                    catch (Exception ex)
                    {
                        tx.Rollback();
                        _logger.Error(ex, "CreateCustomAsync Transaction rollback");
                        throw;
                    }
                }
            }
        }
        public async Task <RemotingResult> QuitAsync(GroupInput input)
        {
            if (!input.Id.HasValue)
            {
                throw new ArgumentNullException("must not be null", nameof(input.Id));
            }

            if (!input.CurrentEmployeeId.HasValue)
            {
                throw new ArgumentNullException("must not be null", nameof(input.CurrentEmployeeId));
            }

            using (var db = new ServiceDbContext(_dbOptions))
            {
                using (var tx = db.Database.BeginTransaction())
                {
                    try
                    {
                        var entity = await db.Groups
                                     .Include(o => o.Members)
                                     .FirstOrDefaultAsync(o => o.Id == input.Id);

                        if (entity == null)
                        {
                            return(RemotingResult.Fail());
                        }

                        var member = entity.Members.Find(o => o.EmployeeId == input.CurrentEmployeeId.Value);
                        if (member == null)
                        {
                            return(RemotingResult.Fail());
                        }
                        if (member.IsOwner)
                        {
                            return(RemotingResult.Fail(FailedCodes.Group_OwnerCannotQuit));
                        }
                        entity.Members.Remove(member);

                        await db.SaveChangesAsync();

                        await _busMs.Publish(new GroupMembersUpdated { Id = entity.Id });

                        await _busMs.Publish(new GroupNotified
                        {
                            Id       = entity.Id,
                            Notifies = new List <EventNotifyDto>
                            {
                                new EventNotifyDto
                                {
                                    Target         = NotifyTargetType.Conversation,
                                    TargetId       = input.Id.ToString(),
                                    Created        = DateTimeOffset.UtcNow,
                                    Text           = input.CurrentEmployeeName,
                                    TargetCategory = (int)GroupEventNotifyType.ParticipantQuited
                                }
                            }
                        });

                        tx.Commit();
                        return(RemotingResult.Success());
                    }
                    catch (Exception ex)
                    {
                        tx.Rollback();
                        _logger.Error(ex, "QuitAsync Transaction rollback");
                        return(RemotingResult.Fail());
                    }
                }
            }
        }
        public async Task <RemotingResult> DeleteAsync(GroupInput input)
        {
            if (!input.Id.HasValue)
            {
                throw new ArgumentNullException("must not be null", nameof(input.Id));
            }

            if (input.CurrentUserId == Guid.Empty)
            {
                throw new ArgumentNullException("must not be empty", nameof(input.CurrentUserId));
            }

            using (var db = new ServiceDbContext(_dbOptions))
            {
                using (var tx = db.Database.BeginTransaction())
                {
                    try
                    {
                        var entity = await db.Groups.FirstOrDefaultAsync(o => o.Id == input.Id);

                        if (entity == null)
                        {
                            return(RemotingResult.Fail());
                        }
                        if (entity.CreatedBy != input.CurrentUserId)
                        {
                            return(RemotingResult.Fail(FailedCodes.Group_NotCreatedBy));
                        }

                        db.Groups.Remove(entity);

                        await db.SaveChangesAsync();

                        await _busMs.Publish(new GroupDeleted { Id = entity.Id });

                        await _busMs.Publish(new GroupNotified
                        {
                            Id       = entity.Id,
                            Notifies = new List <EventNotifyDto>
                            {
                                new EventNotifyDto
                                {
                                    Target         = NotifyTargetType.Conversation,
                                    TargetId       = entity.Id.ToString(),
                                    Created        = DateTimeOffset.UtcNow,
                                    Text           = entity.Name,
                                    TargetCategory = (int)GroupEventNotifyType.GroupDismissed
                                }
                            }
                        });

                        tx.Commit();
                        return(RemotingResult.Success());
                    }
                    catch (Exception ex)
                    {
                        tx.Rollback();
                        _logger.Error(ex, "DeleteAsync Transaction rollback");
                        return(RemotingResult.Fail());
                    }
                }
            }
        }
        public async Task <RemotingResult> UpdateAsync(GroupInput input)
        {
            if (!input.Id.HasValue)
            {
                throw new ArgumentNullException("must not be null", nameof(input.Id));
            }

            if (input.CurrentUserId == Guid.Empty)
            {
                throw new ArgumentNullException("must not be empty", nameof(input.CurrentUserId));
            }

            if (input.RemovingMemberIds?.Count > 0)
            {
                //如果需要删除成员,那么就需要传递当前员工Id
                if (!input.CurrentEmployeeId.HasValue)
                {
                    throw new ArgumentNullException("must not be null", nameof(input.CurrentEmployeeId));
                }

                if (input.RemovingMemberIds.Contains(input.CurrentEmployeeId.Value))
                {
                    return(RemotingResult.Fail(FailedCodes.Group_CannotRemoveOwner));
                }
            }

            using (var db = new ServiceDbContext(_dbOptions))
            {
                using (var tx = db.Database.BeginTransaction())
                {
                    try
                    {
                        var entity = await db.Groups.FirstOrDefaultAsync(o => o.Id == input.Id);

                        if (entity == null)
                        {
                            return(RemotingResult.Fail());
                        }
                        if (entity.CreatedBy != input.CurrentUserId)
                        {
                            return(RemotingResult.Fail(FailedCodes.Group_NotCreatedBy));
                        }

                        var nameUpdated = false;
                        if (!string.IsNullOrWhiteSpace(input.Name) && entity.Name != input.Name)
                        {
                            entity.Name = input.Name;
                            nameUpdated = true;
                        }

                        if (input.Remark != null)
                        {
                            entity.Remark = input.Remark;
                        }

                        var membersUpdated = false;
                        if (input.AddingMemberIds?.Count > 0 ||
                            input.RemovingMemberIds?.Count > 0)
                        {
                            //需要编辑成员,就显式加载成员集合
                            await db.Entry(entity).Collection(o => o.Members).LoadAsync();

                            membersUpdated = true;
                        }

                        if (input.AddingMemberIds != null)
                        {
                            foreach (var employeeId in input.AddingMemberIds)
                            {
                                if (!entity.Members.Exists(o => o.EmployeeId == employeeId))
                                {
                                    entity.Members.Add(new GroupMember
                                    {
                                        EmployeeId = employeeId,
                                        GroupId    = input.Id.Value,
                                        Joined     = DateTimeOffset.UtcNow,
                                    });
                                }
                            }
                        }

                        if (input.RemovingMemberIds != null)
                        {
                            var willRemoving = new List <GroupMember>();
                            foreach (var employeeId in input.RemovingMemberIds)
                            {
                                var m = entity.Members.Find(o => o.EmployeeId == employeeId);
                                willRemoving.Add(m);
                            }
                            willRemoving.ForEach(o => entity.Members.Remove(o));
                        }

                        await db.SaveChangesAsync();

                        if (membersUpdated)
                        {
                            await _busMs.Publish(new GroupMembersUpdated { Id = entity.Id });
                        }

                        await SendEventNotifyForUpdateAsync(nameUpdated, input);

                        tx.Commit();
                        return(RemotingResult.Success());
                    }
                    catch (Exception ex)
                    {
                        tx.Rollback();
                        _logger.Error(ex, "UpdateAsync Transaction rollback");
                        return(RemotingResult.Fail());
                    }
                }
            }
        }