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