Esempio n. 1
0
        public async Task <ActionResult> Post(string name, [FromBody] RegionCreationInfo creationInfo)
        {
            // _logger.LogInformation("Image Base64: {0}", creationInfo.ImageBase64);

            var region = new PostRegionEntity {
                Title = name
            };

            if (!string.IsNullOrEmpty(creationInfo?.ImageBase64))
            {
                region.IconData = Convert.FromBase64String(creationInfo.ImageBase64);
            }

            try
            {
                _dataFacade.AddPostRegion(region);
                await _dataFacade.CommitChanges();
            }
            catch (DataFacadeException)
            {
                // name 字段不合法
                return(BadRequest());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "向数据源添加板块时抛出异常:{0}:{1}", ex.GetType(), ex.Message);
                throw;
            }

            return(Ok());
        }
        /// <summary>
        /// 向数据源中添加帖子。
        /// </summary>
        /// <param name="dataFacade">数据源的外观。</param>
        /// <param name="indexEntity">帖子索引实体对象。</param>
        /// <param name="contentEntity">帖子内容对象。</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="dataFacade"/>为null
        ///     或
        ///     <paramref name="indexEntity"/>为null
        ///     或
        ///     <paramref name="contentEntity"/>为null
        /// </exception>
        /// <exception cref="DataFacadeException">数据源抛出了未经处理的异常</exception>
        public static async Task <int> AddPost(this IDataFacade dataFacade,
                                               PostEntity indexEntity, PostContentEntity contentEntity)
        {
            if (dataFacade == null)
            {
                throw new ArgumentNullException(nameof(dataFacade));
            }
            if (indexEntity == null)
            {
                throw new ArgumentNullException(nameof(indexEntity));
            }
            if (contentEntity == null)
            {
                throw new ArgumentNullException(nameof(contentEntity));
            }

            // 将内容实体对象插入到数据源中。
            await dataFacade.AddPostContentEntity(contentEntity);

            // 将帖子索引实体对象插入到数据源中。
            dataFacade.AddPostIndexEntity(indexEntity);
            await dataFacade.CommitChanges();

            return(indexEntity.Id);
        }
        /// <summary>
        /// 移除帖子图片。
        /// </summary>
        /// <param name="dataFacade"></param>
        /// <param name="postId">帖子 ID。</param>
        /// <param name="indexesToRemove">要移除的图片索引。</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="dataFacade"/>为null
        ///     或
        ///     <paramref name="indexesToRemove"/>为null
        /// </exception>
        /// <exception cref="PostNotFoundException">指定的帖子不存在。</exception>
        public static async Task RemovePostImages(this IDataFacade dataFacade,
                                                  int postId, IEnumerable <int> indexesToRemove)
        {
            if (dataFacade == null)
            {
                throw new ArgumentNullException(nameof(dataFacade));
            }
            if (indexesToRemove == null)
            {
                throw new ArgumentNullException(nameof(indexesToRemove));
            }

            // TODO: 在这里添加代码对 indexesToRemove 进行验证

            var indexEntity = await dataFacade.Posts
                              .Where(e => e.Id == postId)
                              .FirstOrDefaultAsync();

            if (indexEntity == null)
            {
                throw new PostNotFoundException();
            }

            var contentId     = new ObjectId(indexEntity.ContentId);
            var contentEntity = await dataFacade.FindPostContentEntity(contentId);

            var indexesToRemoveConcrete = indexesToRemove.ToArray();

            // 删除图片数据
            var removeTasks = new List <Task>();

            foreach (var imageIndex in indexesToRemoveConcrete.Where(i => i >= 0 && i < contentEntity.ImageIds.Length))
            {
                var imageId = contentEntity.ImageIds[imageIndex];
                if (imageId == null)
                {
                    continue;
                }

                removeTasks.Add(dataFacade.RemoveImage(imageId.Value));
            }

            await Task.WhenAll(removeTasks);

            // 更新内容实体对象
            var imageSetDict = indexesToRemoveConcrete.ToDictionary <int, int, ObjectId?>(i => i, i => null);
            await dataFacade.UpdatePostContentImageIds(contentId, imageSetDict);

            // 更新索引实体对象中的最后更新时间戳
            indexEntity.UpdateTime = DateTime.Now;
            await dataFacade.CommitChanges();
        }
        /// <summary>
        /// 当给定的用户不存在时,向数据源添加用户。返回用户实体对象。
        /// </summary>
        /// <param name="dataFacade">数据源外观。</param>
        /// <param name="wechatId">用户的微信 ID。</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="dataFacade"/> 为 null
        ///     或
        ///     <paramref name="wechatId"/> 为 null
        /// </exception>
        public static async Task <UserEntity> AddOrFindUserByWechatId(this IDataFacade dataFacade, string wechatId)
        {
            if (dataFacade == null)
            {
                throw new ArgumentNullException(nameof(dataFacade));
            }
            if (wechatId == null)
            {
                throw new ArgumentNullException(nameof(wechatId));
            }

            var existingEntity = await dataFacade.Users
                                 .Where(u => u.WechatId == wechatId)
                                 .FirstOrDefaultAsync();

            if (existingEntity != null)
            {
                // 用户已经存在于数据源中
                return(existingEntity);
            }

            // 用户在数据源中未找到
            var userEntity = new UserEntity
            {
                WechatId = wechatId
            };

            try
            {
                dataFacade.AddUser(userEntity);
                await dataFacade.CommitChanges();

                return(userEntity);
            }
            catch (DataFacadeException)
            {
                // 重做用户查询
                existingEntity = await dataFacade.Users
                                 .Where(u => u.WechatId == wechatId)
                                 .FirstOrDefaultAsync();

                if (existingEntity != null)
                {
                    return(existingEntity);
                }

                // 重做用户查询仍然无法找到用户
                throw;
            }
        }
        /// <summary>
        /// 向数据源添加评论索引实体对象及其对应的内容实体对象。
        /// </summary>
        /// <param name="dataFacade"></param>
        /// <param name="indexEntity">要添加的索引实体对象。</param>
        /// <param name="contentEntity">要添加的内容实体对象。</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="indexEntity"/>为null
        ///     或
        ///     <paramref name="contentEntity"/>为null
        /// </exception>
        public static async Task AddPostComment(this IDataFacade dataFacade,
                                                CommentEntity indexEntity, CommentContentEntity contentEntity)
        {
            if (indexEntity == null)
            {
                throw new ArgumentNullException(nameof(indexEntity));
            }
            if (contentEntity == null)
            {
                throw new ArgumentNullException(nameof(contentEntity));
            }

            dataFacade.AddCommentIndexEntity(indexEntity);
            await dataFacade.CommitChanges();

            await dataFacade.AddCommentContentEntity(contentEntity);
        }
        /// <summary>
        /// 删除指定的帖子。
        /// </summary>
        /// <param name="dataFacade"></param>
        /// <param name="postId">要删除的帖子 ID。</param>
        /// <param name="permanent">是否永久性地删除帖子数据</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="dataFacade"/>为null
        /// </exception>
        /// <exception cref="DataFacadeException">当数据源抛出了未经处理的异常时抛出</exception>
        public static async Task RemovePost(this IDataFacade dataFacade, int postId, bool permanent = false)
        {
            if (dataFacade == null)
            {
                throw new ArgumentNullException(nameof(dataFacade));
            }
            if (permanent)
            {
                throw new NotImplementedException();
            }

            var indexEntity = await dataFacade.Posts
                              .Where(e => e.Id == postId && e.IsRemoved == false)
                              .FirstOrDefaultAsync();

            if (indexEntity == null)
            {
                throw new PostNotFoundException();
            }

            indexEntity.IsRemoved = true;
            await dataFacade.CommitChanges();
        }
        /// <summary>
        /// 向给定的帖子上传图片。
        /// </summary>
        /// <param name="dataFacade"></param>
        /// <param name="postId">帖子 ID。</param>
        /// <param name="images">图片 ID 及对应图片的数据流工厂。</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="images"/>为null
        /// </exception>
        /// <exception cref="PostNotFoundException">
        ///     指定的帖子不存在
        ///     或
        ///     帖子存在但其删除标记为true
        /// </exception>
        public static async Task UpdatePostImages(this IDataFacade dataFacade,
                                                  int postId, IReadOnlyDictionary <int, Func <Stream> > images)
        {
            if (images == null)
            {
                throw new ArgumentNullException(nameof(images));
            }

            // TODO: 在这里添加代码对 images 执行验证

            var indexEntity = await dataFacade.Posts
                              // 下面的语句中务必使用 e.IsRemoved == true 以正确引导 EF Core 建立查询
                              .Where(e => e.Id == postId && e.IsRemoved == false)
                              .FirstOrDefaultAsync();

            if (indexEntity == null)
            {
                // 指定的帖子不存在
                throw new PostNotFoundException();
            }

            var contentId     = new ObjectId(indexEntity.ContentId);
            var contentEntity = await dataFacade.FindPostContentEntity(contentId);

            // 删除已有的、被覆盖的图片数据
            var removeTasks = new List <Task>();

            foreach (var imageIndex in images.Keys.Where(i => i >= 0 && i < contentEntity.ImageIds.Length))
            {
                var imageId = contentEntity.ImageIds[imageIndex];
                if (imageId == null)
                {
                    continue;
                }

                removeTasks.Add(dataFacade.RemoveImage(imageId.Value));
            }

            await Task.WhenAll(removeTasks);

            // 将图片上传至数据源
            var imageIds    = new ConcurrentDictionary <int, ObjectId?>();
            var uploadTasks = new List <Task>();

            foreach (var(index, imageDataStreamFactory) in images)
            {
                var imageDataStream = imageDataStreamFactory();
                uploadTasks.Add(dataFacade.UploadImage(imageDataStream)
                                .ContinueWith((t, i) =>
                {
                    imageDataStream.Close();
                    imageIds.TryAdd((int)i, t.Result);
                }, index));
            }

            await Task.WhenAll(uploadTasks);

            // 更新内容实体对象
            await dataFacade.UpdatePostContentImageIds(contentId, imageIds);

            // 更新索引实体对象中的上次更新时间戳
            indexEntity.UpdateTime = DateTime.Now;
            await dataFacade.CommitChanges();
        }