public async Task <TaskAggregate> CreateTaskAsync(TaskModel newTask, TaskCollections collections, OutboxMessageModel outboxMessage)
        {
            string insertQuery = $"insert into {_tableName} (id, title, description, listid, state, duedate, version, createddate) " +
                                 $"values('{newTask.Id}', '{newTask.Title}', '{newTask.Description}', '{newTask.ListId}', {(int)newTask.State}, " +
                                 $"{GetQueryNullableEscapedValue(newTask.DueDate)}, {newTask.Version}, {GetQueryNullableEscapedValue(newTask.CreatedDate)});";

            Task <string> insertTaskMembersQueryTask = ConstructQueryToAddTaskMembersAsync(newTask.Id, collections.Members);
            await         insertTaskMembersQueryTask;

            Task <string> insertTaskLabelsQueryTask = ConstructQueryToAddTaskLabelsAsync(newTask.Id, collections.Labels);
            await         insertTaskLabelsQueryTask;

            //await Task.WhenAll(insertTaskMembersQueryTask, insertTaskLabelsQueryTask);

            insertTaskMembersQueryTask.CheckAndThrowIfFaulted();
            insertTaskLabelsQueryTask.CheckAndThrowIfFaulted();
            string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage);

            insertQuery += insertTaskMembersQueryTask.Result;
            insertQuery += insertTaskLabelsQueryTask.Result;
            insertQuery += insertOutboxMessageQuery;

            int res = await _connection.ExecuteAsync(insertQuery);

            if (res <= 0)
            {
                throw new DatabaseException("Add task failed");
            }

            return(await GetTaskAsync(newTask.Id));
        }
        public async Task <TaskAggregate> CreateTaskAsync(TaskModel newTask,
                                                          IEnumerable <string> usersIds, IEnumerable <string> labelsIds, string requestId)
        {
            if (!(await CheckAndSaveRequestIdAsync(requestId)))
            {
                throw new AlreadyHandledException();
            }

            try
            {
                newTask.Init();

                TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(newTask, usersIds, labelsIds);

                var list = taskData.List;

                var taskCollections = new TaskCollections
                {
                    Members = usersIds,
                    Labels  = labelsIds
                };

                var membersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(taskData.Users);
                var labelsRecords  = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(taskData.Labels);

                var outboxMessage = OutboxMessageModel.Create(
                    new TaskCreatedMessage
                {
                    TaskId       = newTask.Id,
                    Title        = newTask.Title,
                    ProjectId    = list.ProjectId,
                    ProjectTitle = list.ProjectTitle,
                    ListId       = list.Id,
                    ListTitle    = list.Title,
                    Members      = membersRecords,
                    Labels       = labelsRecords
                }, Topics.Tasks, MessageActions.Created);

                var createdTask = await _tasksRepository.CreateTaskAsync(newTask, taskCollections, outboxMessage);

                List <Task> cacheInvalidationTasks = new List <Task>();
                foreach (var user in usersIds)
                {
                    string userCacheKey = string.Format(CacheSettings.UserTasksCacheKeyPattern, user);
                    cacheInvalidationTasks.Add(_cache.RemoveAsync(userCacheKey));
                }

                await Task.WhenAll(cacheInvalidationTasks);

                return(createdTask);
            }
            catch (Exception)
            {
                //rollback request id
                await _requestsRepository.DeleteRequestIdAsync(requestId);

                throw;
            }
        }
        public async Task <TaskAggregate> CreateTaskAsync(TaskModel newTask,
                                                          IEnumerable <string> usersIds, IEnumerable <string> labelsIds, string requestId)
        {
            if (!(await CheckAndSaveRequestIdAsync(requestId)))
            {
                throw new AlreadyHandledException();
            }

            try
            {
                newTask.Init();

                TaskRelatedData taskData = await GetAndCheckTaskRelatedDataAsync(newTask, usersIds, labelsIds);

                var list = taskData.List;

                var taskCollections = new TaskCollections
                {
                    Members = usersIds,
                    Labels  = labelsIds
                };

                var membersRecords = _mapper.Map <IEnumerable <UserModel>, IEnumerable <TaskUserRecord> >(taskData.Users);
                var labelsRecords  = _mapper.Map <IEnumerable <LabelModel>, IEnumerable <TaskLabelRecord> >(taskData.Labels);

                var outboxMessage = OutboxMessageModel.Create(
                    new TaskCreatedMessage
                {
                    TaskId       = newTask.Id,
                    Title        = newTask.Title,
                    ProjectId    = list.ProjectId,
                    ProjectTitle = list.ProjectTitle,
                    ListId       = list.Id,
                    ListTitle    = list.Title,
                    Members      = membersRecords,
                    Labels       = labelsRecords
                }, Topics.Tasks, MessageActions.Created);

                return(await _tasksRepository.CreateTaskAsync(newTask, taskCollections, outboxMessage));
            }
            catch (Exception)
            {
                //rollback request id
                await _requestsRepository.DeleteRequestIdAsync(requestId);

                throw;
            }
        }
        public async Task <TaskAggregate> UpdateTaskAsync(TaskModel updatingTask, TaskCollections addingCollections,
                                                          TaskCollections removingCollections, OutboxMessageModel outboxMessage)
        {
            string taskId = updatingTask.Id;

            int version = updatingTask.Version + 1;

            var updateQuery = $"update {_tableName} set " +
                              $"title = '{updatingTask.Title}', " +
                              $"description = '{updatingTask.Description}', " +
                              $"listid = '{updatingTask.ListId}', " +
                              $"state = {(int)updatingTask.State}, " +
                              $"duedate = {GetQueryNullableEscapedValue(updatingTask.DueDate)}, " +
                              $"version = {updatingTask.Version} " +
                              $"where id = '{taskId}'; ";

            string deleteOldTaskMembersQuery = ConstructQueryToDeleteTaskMembers(taskId, removingCollections.Members);
            string deleteOldTaskLabelsQuery  = ConstructQueryToDeleteTaskLabels(taskId, removingCollections.Labels);

            Task <string> addNewTaskMembersQueryTask = ConstructQueryToAddTaskMembersAsync(taskId, addingCollections.Members);
            await         addNewTaskMembersQueryTask;

            Task <string> addNewTaskLabelsQueryTask = ConstructQueryToAddTaskLabelsAsync(taskId, addingCollections.Labels);
            await         addNewTaskLabelsQueryTask;

            //await Task.WhenAll(addNewTaskMembersQueryTask, addNewTaskLabelsQueryTask);

            addNewTaskMembersQueryTask.CheckAndThrowIfFaulted();
            addNewTaskLabelsQueryTask.CheckAndThrowIfFaulted();

            string insertOutboxMessageQuery = ConstructInsertMessageQuery(outboxMessage);

            updateQuery += deleteOldTaskMembersQuery;
            updateQuery += deleteOldTaskLabelsQuery;
            updateQuery += addNewTaskMembersQueryTask.Result;
            updateQuery += addNewTaskLabelsQueryTask.Result;
            updateQuery += insertOutboxMessageQuery;

            int res = await _connection.ExecuteAsync(updateQuery);

            if (res <= 0)
            {
                throw new DatabaseException("Update task failed");
            }

            return(await GetTaskAsync(updatingTask.Id));
        }