asp.net-mvc – 如何优雅地重新附加Entity Framework 5 POCO结构
我正在使用Entity Framework 5(数据库优先,生成POCO)进行数据访问的MVC4 Web应用程序.
在应用程序中,用户经历多个屏幕,创建或编辑文档(称为“案例研究”).当他们到达最终屏幕时,他们的文档在内存中作为CaseStudy POCO存在,并且在将此结构保存到数据库之前一切都很好. 为了存储文档,我定义了几个数据库表,这些表又映射到业务层使用的EF POCO,然后由MVC控制器使用.因此,短期DbContexts用于检索POCO并将它们存储在请求之间的会话中. 因此,保存屏幕必须将具有导航属性的此POCO的内容保存到现有表数据(类别,布局和部分表),以及添加或更新的数据(CaseStudySections和CaseStudy本身).所以所有的POCO都是新的,或者用于检索它们的上下文早已被处理掉了.换句话说,它们都是“超然的”. 这篇文章的不寻常之处在于我已经掌握了可行的解决方案.问题是它体积大,脆而且不雅.我发布下面的代码.注意通过子集合的迭代,显式添加和附加,必须获得一个入口对象并将各个属性标记为已修改,以便它们将被更新,最后可怕的歌曲和舞蹈以使AdditionalMaterials集合同步.如果这是处理EF5中脱离的POCO所需要的,我会感到失望. 我在这里错过了什么吗?这与最佳做法一致吗?是否有更优雅和/或简洁的方法来附加POCO结构并插入/更新? 保存案例研究的代码: public void SaveCaseStudy(CaseStudy caseStudy) { foreach (var s in caseStudy.CaseStudySections) { this.Entities.Sections.Attach(s.Section); if (s.CreatedByRefId == default(Guid)) { s.CreatedByRefId = this.UserRefId; s.CreatedTime = DateTime.Now; this.Entities.CaseStudySections.Add(s); } else { this.Entities.CaseStudySections.Attach(s); var entry = this.Entities.Entry(s); entry.Property(e => e.TextData).IsModified = true; entry.Property(e => e.BinaryData).IsModified = true; } s.LastModifiedByRefId = this.UserRefId; s.LastModifiedTime = DateTime.Now; } foreach (var m in caseStudy.AdditionalMaterials) { if (m.CreatedByRefId == default(Guid)) { m.CreatedByRefId = this.UserRefId; m.CreatedTime = DateTime.Now; this.Entities.AdditionalMaterials.Add(m); } else { this.Entities.AdditionalMaterials.Attach(m); } m.LastModifiedByRefId = this.UserRefId; m.LastModifiedByTime = DateTime.Now; } this.Entities.Layouts.Attach(caseStudy.Layout); this.Entities.Categories.Attach(caseStudy.Category); if (caseStudy.CreatedByRefId != default(Guid)) { this.Entities.CaseStudies.Attach(caseStudy); var entry = this.Entities.Entry(caseStudy); entry.Property(e => e.CaseStudyName).IsModified = true; entry.Property(e => e.CaseStudyTitle).IsModified = true; } else { this.Entities.CaseStudies.Add(caseStudy); caseStudy.CreatedByRefId = this.UserRefId; caseStudy.CreatedTime = DateTime.Now; } caseStudy.LastModifiedByRefId = this.UserRefId; caseStudy.LastModifiedTime = DateTime.Now; if (caseStudy.CaseStudyStatus != (int)CaseStudyStatus.Personalized) { caseStudy.CaseStudyStatus = (int)CaseStudyStatus.PendingApproval; } caseStudy.ApprovedByRefId = null; caseStudy.ApprovedTime = null; this.Entities.SaveChanges(); var existingAdditionalMaterialRefIds = caseStudy.AdditionalMaterials .Select(m => m.AdditionalMaterialRefId) .ToArray(); var additionalMaterialsToRemove = this.Entities.AdditionalMaterials .Where(m => m.CaseStudyRefId == caseStudy.CaseStudyRefId && !existingAdditionalMaterialRefIds.Contains(m.AdditionalMaterialRefId)) .ToArray(); foreach (var additionalMaterialToRemove in additionalMaterialsToRemove) { this.Entities.AdditionalMaterials.Remove(additionalMaterialToRemove); } this.Entities.SaveChanges(); } 解决方法
一般来说,这是你必须要做的.在附加分离对象图时,您必须告知EF有关要执行的每个更改.我不是说您的代码不能简化,但是如果您想要添加或修改它,您仍然必须处理每个实体并设置其状态.
Here有点老了,但仍然是关于这个主题的有效答案 – 简而言之,自从我写这篇文章后没有任何变化,只创建了新的DbContext API,它仍然位于旧API之上.到目前为止,我所看到的这个主题的最佳描述见书Programming Entity Framework: DbContext. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 如何循环通过WebForms中的数据,就像在MVC中
- asp.net-web-api – 没有IQueryable的OData
- asp.net – 在iframe中丢失会话状态,但不在弹出窗口中
- asp.net-mvc-3 – 在MVC3中对Webgrid行进行内联编辑
- asp.net – 如何使用AntiXss Library正确清理内容?
- asp.net – 报表查看器Web控件HTTP处理程序尚未在应用程序的
- asp.net-mvc – ASP.NET MVC6中的实体框架7多个外键到同一个
- asp.net mvc中配置全局异常过滤器
- asp.net-mvc – ASP.NET MVC:无法在我的控制器中获取字符串
- asp.net – UserControl属性中的默认值