/// <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="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();
        }