ADO.NET Entity多对多场景下添加产品关联图片后关联表无数据咨询
问题背景
我需要实现上传图片并关联到对应产品的功能,涉及3张数据库表,结构如下:
---- TWebProducts ----
- intWebProductID
- ... 其余无关字段省略
---- TWebProductImages ----
- intWebProductID
- intWebImageID
---- TWebImages ----
- intWebImageID
- varImage
我编写了如下实现代码,但运行后未生效:
[HttpPost] public ActionResult ProductEdit(IEnumerable<HttpPostedFileBase> files, TWebProduct tbl, HttpPostedFileBase file) { // 缩略图处理 if (file != null) { string path = null; string pic = null; pic = System.IO.Path.GetFileName(file.FileName); path = System.IO.Path.Combine(Server.MapPath("~/ProductThumbnails/"), pic); // 保存上传文件 file.SaveAs(path); tbl.varThumbnailImage = pic; } tbl.dteModified = DateTime.Now; tbl.intCompanyID = 1; // 更新图片关联 string fName = ""; try { // 遍历所有上传文件 foreach (var img in files) { // 保存文件逻辑 fName = img.FileName; if (img != null && img.ContentLength > 0) { #region 图片保存逻辑 var originalDirectory = new DirectoryInfo(string.Format("{0}ProductImages\\", Server.MapPath(@"\"))); //string pathString = System.IO.Path.Combine(originalDirectory.ToString(), "imagepath"); string pathString = originalDirectory.ToString(); var fileName1 = Path.GetFileName(img.FileName); bool isExists = System.IO.Directory.Exists(pathString); if (!isExists) System.IO.Directory.CreateDirectory(pathString); var path = string.Format("{0}\\{1}", pathString, img.FileName); img.SaveAs(path); #endregion // 核心逻辑部分 // 构造图片实体 TWebImage webImage = new TWebImage(); webImage.varImage = path; // 将图片添加到产品的图片导航属性中,建立关联 tbl.TWebImages.Add(webImage); } } // 调用仓储更新产品信息 _unitOfWork.GetRepositoryInstance<TWebProduct>().Update(tbl); } catch (Exception ex) { } return RedirectToAction("Products"); }
问题现象
代码运行无报错,但TWebImages表和中间关联表TWebProductImages均无数据写入。
解决方案
按以下顺序排查修复即可:
- 补全异常捕获逻辑
当前catch块为空,所有运行时异常都被直接吞掉,无法定位问题。先在catch块中添加日志输出逻辑,确认代码运行过程中没有异常:
catch (Exception ex) { // 此处输出异常日志,比如用Debug、log4net等工具打印ex.ToString() Debug.WriteLine(ex.Message); throw; // 调试阶段可以直接抛出异常方便定位 }
- 确认UnitOfWork提交了更改
绝大多数仓储模式的Update方法仅修改实体的跟踪状态,不会直接提交到数据库,你需要在调用Update之后手动调用UnitOfWork的提交方法:
_unitOfWork.GetRepositoryInstance<TWebProduct>().Update(tbl); // 新增提交代码,根据你UnitOfWork的实现调整方法名,常见为SaveChanges/Commit _unitOfWork.SaveChanges();
- 修复EF多对多关联实体的跟踪逻辑
你当前传入的tbl是前端传参反序列化得到的游离态实体,EF默认不会跟踪其导航属性下新增的TWebImage实体,有两种修复方案:
- 方案1:先单独插入图片实体,再手动关联
// 构造图片实体 TWebImage webImage = new TWebImage(); webImage.varImage = path; // 先插入图片表获取自增ID _unitOfWork.GetRepositoryInstance<TWebImage>().Add(webImage); _unitOfWork.SaveChanges(); // 再构造中间表关联 TWebProductImage relation = new TWebProductImage(); relation.intWebProductID = tbl.intWebProductID; relation.intWebImageID = webImage.intWebImageID; _unitOfWork.GetRepositoryInstance<TWebProductImage>().Add(relation);
- 方案2:先Attach产品实体到上下文,再添加关联
// 先把产品实体附加到上下文跟踪 var productRepo = _unitOfWork.GetRepositoryInstance<TWebProduct>(); productRepo.Attach(tbl); // 再添加图片关联,EF会自动识别新增的子实体和中间表关系 tbl.TWebImages.Add(webImage); productRepo.Update(tbl);
- 验证EF多对多配置是否正确
确认你的DbContext中已经正确配置了TWebProduct和TWebImage的多对多关系,示例Fluent API配置如下:
modelBuilder.Entity<TWebProduct>() .HasMany(p => p.TWebImages) .WithMany(i => i.TWebProducts) .Map(m => { m.MapLeftKey("intWebProductID"); m.MapRightKey("intWebImageID"); m.ToTable("TWebProductImages"); });
- 检查入参是否有效
加断点验证files参数是否有值,foreach循环是否真的执行到了添加关联的逻辑,避免因为前端表单的文件上传控件name不匹配导致files为空的问题。
内容的提问来源于stack exchange,提问作者Scott Uphus
相关产品推荐
相关产品推荐

