예제 #1
0
        /// <summary>
        /// Constructs a list of hierarchical DTOs with all message data for a page. This is a list of DTOs as the attachments information is
        /// fetched as well, which have a 1:n relationship with message.
        /// </summary>
        /// <param name="threadId">ID of Thread which messages should be returned</param>
        /// <param name="pageNo">The page no.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <returns>List with all messages in the thread for the page specified</returns>
        public static async Task <List <MessageInThreadDto> > GetAllMessagesInThreadAsDTOsAsync(int threadId, int pageNo, int pageSize)
        {
            using (var adapter = new DataAccessAdapter())
            {
                var metaData = new LinqMetaData(adapter);
                var q        = metaData.Message
                               .Where(m => m.ThreadID == threadId)
                               .OrderBy(m => m.PostingDate)
                               .TakePage(pageNo, pageSize);
                var messages = await q.ProjectToMessageInThreadDto().ToListAsync().ConfigureAwait(false);

                // update thread entity directly inside the DB with an update statement so the # of views is increased by one.
                var updater = new ThreadStatisticsEntity();
                // set the NumberOfViews field to an expression which increases it by 1
                updater.Fields[(int)ThreadStatisticsFieldIndex.NumberOfViews].ExpressionToApply = (ThreadStatisticsFields.NumberOfViews + 1);
                await adapter.UpdateEntitiesDirectlyAsync(updater, new RelationPredicateBucket(ThreadStatisticsFields.ThreadID == threadId)).ConfigureAwait(false);

                return(messages);
            }
        }
예제 #2
0
        /// <summary>
        /// Deletes the given message from the database and the complete logged history.
        /// </summary>
        /// <param name="messageId">The ID of the message to delete</param>
        /// <param name="threadId">The id of the thread the message is part of</param>
        /// <returns>True if succeeded, false otherwise</returns>
        public static async Task <bool> DeleteMessageAsync(int messageId, int threadId)
        {
            using (var adapter = new DataAccessAdapter())
            {
                // if the message was the last message in the thread, we have first to update the statistics entity with the message that's semi-last.
                // we do that by simply fetching the last two messages of the thread. if the last message of these 2 is the one to delete, we update
                // the statistics entity with the one that's semi-last.
                var qf = new QueryFactory();
                var q  = qf.Message
                         .Where(MessageFields.ThreadID.Equal(threadId))
                         .OrderBy(MessageFields.PostingDate.Descending())
                         .Limit(2)
                         .Select(() => MessageFields.MessageID.ToValue <int>());
                var lastTwoMessageIdsInThread = await adapter.FetchQueryAsync(q).ConfigureAwait(false);

                await adapter.StartTransactionAsync(IsolationLevel.ReadCommitted, "DeleteMessage").ConfigureAwait(false);

                try
                {
                    var threadStatisticsUpdater = new ThreadStatisticsEntity();
                    threadStatisticsUpdater.Fields[(int)ThreadStatisticsFieldIndex.NumberOfMessages].ExpressionToApply = (ThreadStatisticsFields.NumberOfMessages - 1);
                    if (lastTwoMessageIdsInThread.Count == 2 && lastTwoMessageIdsInThread[0] == messageId)
                    {
                        // message is the last one in the thread, update statistics row with the new last one
                        threadStatisticsUpdater.LastMessageID = lastTwoMessageIdsInThread[1];
                        await adapter.UpdateEntitiesDirectlyAsync(threadStatisticsUpdater, new RelationPredicateBucket(ThreadStatisticsFields.ThreadID.Equal(threadId)))
                        .ConfigureAwait(false);
                    }

                    await DeleteMessagesAsync(MessageFields.MessageID.Equal(messageId), adapter);

                    adapter.Commit();
                    return(true);
                }
                catch
                {
                    adapter.Rollback();
                    throw;
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Updates the user/forum/thread statistics after a message insert. Also makes sure if the thread isn't in a queue and the forum has a default support
        /// queue that the thread is added to that queue
        /// </summary>
        /// <param name="threadId">The thread ID.</param>
        /// <param name="userId">The user ID.</param>
        /// <param name="newMessageId">The message id of the new message posted in the thread with threadid. If 0 or lower it's ignored and threadstatistics
        /// aren't updated. This is the case for when a new thread: the first message insert already inserted a correct threadstatistics object. </param>
        /// <param name="adapter">The adapter to use, which is assumed to have a live transaction active</param>
        /// <param name="postingDate">The posting date.</param>
        /// <param name="addToQueueIfRequired">if set to true, the thread will be added to the default queue of the forum the thread is in, if the forum
        /// has a default support queue and the thread isn't already in a queue.</param>
        /// <param name="subscribeToThread">if set to <c>true</c> [subscribe to thread].</param>
        /// <remarks>
        /// Leaves the passed in transaction open, so it doesn't commit/rollback, it just performs a set of actions inside the
        /// passed in transaction.
        /// </remarks>
        internal static async Task UpdateStatisticsAfterMessageInsert(int threadId, int userId, int newMessageId, IDataAccessAdapter adapter, DateTime postingDate,
                                                                      bool addToQueueIfRequired, bool subscribeToThread)
        {
            // user statistics
            var userUpdater = new UserEntity();

            // set the amountofpostings field to an expression so it will be increased with 1. Update the entity directly in the DB
            userUpdater.Fields[(int)UserFieldIndex.AmountOfPostings].ExpressionToApply = (UserFields.AmountOfPostings + 1);
            await adapter.UpdateEntitiesDirectlyAsync(userUpdater, new RelationPredicateBucket(UserFields.UserID.Equal(userId)))
            .ConfigureAwait(false);

            if (newMessageId > 0)
            {
                // thread statistics. Create a single Update query which updates the messageid and increases the number of messages value with 1
                var threadStatisticsUpdater = new ThreadStatisticsEntity {
                    LastMessageID = newMessageId
                };
                threadStatisticsUpdater.Fields[(int)ThreadStatisticsFieldIndex.NumberOfMessages].ExpressionToApply = (ThreadStatisticsFields.NumberOfMessages + 1);
                await adapter.UpdateEntitiesDirectlyAsync(threadStatisticsUpdater, new RelationPredicateBucket(ThreadStatisticsFields.ThreadID.Equal(threadId)))
                .ConfigureAwait(false);
            }

            // unmark the thread as done if it's done
            var threadUpdater = new ThreadEntity()
            {
                MarkedAsDone = false
            };
            await adapter.UpdateEntitiesDirectlyAsync(threadUpdater, new RelationPredicateBucket(ThreadFields.ThreadID.Equal(threadId)))
            .ConfigureAwait(false);

            // forum statistics. Load the forum from the DB, as we need it later on. Use a nested query to fetch the forum as we don't know the
            // forumID as we haven't fetched the thread
            var qf = new QueryFactory();
            var q  = qf.Forum
                     .Where(ForumFields.ForumID.In(qf.Create()
                                                   .Select(ThreadFields.ForumID)
                                                   .Where(ThreadFields.ThreadID.Equal(threadId))));
            var containingForum = await adapter.FetchFirstAsync(q).ConfigureAwait(false);

            if (containingForum != null)
            {
                containingForum.ForumLastPostingDate = postingDate;

                // save the forum.
                await adapter.SaveEntityAsync(containingForum, true).ConfigureAwait(false);

                if (addToQueueIfRequired && containingForum.DefaultSupportQueueID.HasValue)
                {
                    // If the thread involved isn't in a queue, place it in the default queue of the forum (if applicable)
                    var containingQueue = await SupportQueueGuiHelper.GetQueueOfThreadAsync(threadId, adapter);

                    if (containingQueue == null)
                    {
                        // not in a queue, and the forum has a default queue. Add the thread to the queue of the forum
                        await SupportQueueManager.AddThreadToQueueAsync(threadId, containingForum.DefaultSupportQueueID.Value, userId, adapter);
                    }
                }
            }

            //subscribe to thread if indicated
            if (subscribeToThread)
            {
                await UserManager.AddThreadToSubscriptionsAsync(threadId, userId, adapter);
            }
        }