Jim*_*ble 5 asp.net-mvc entity-framework poco entity-framework-5
我正在使用Entity Framework 5(数据库优先,生成POCO)进行数据访问的MVC4 Web应用程序.
在应用程序中,用户经历多个屏幕,创建或编辑文档(称为"案例研究").当他们到达最终屏幕时,他们的文档在内存中作为CaseStudy POCO存在,并且在将此结构保存到数据库之前一切都很好.
为了存储文档,我定义了几个数据库表,这些表又映射到业务层使用的EF POCO,然后由MVC控制器使用.因此,短期DbContexts用于检索POCO并将它们存储在请求之间的会话中.
其结果是,保存屏幕必须保存此POCO具有导航属性现有表的数据(类别,布局,和部分表)的内容,并且还添加或更新的数据(CaseStudySections和案例研究本身).所以所有的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();
}
Run Code Online (Sandbox Code Playgroud)
一般来说,这是你必须做的。在附加分离对象图时,您必须告诉 EF 您想要执行的每个更改。我并不是说您的代码不能简化,但如果您希望添加或修改它,您仍然必须处理每个实体并设置其状态。
这是关于该主题的有点旧但仍然有效的答案 - 简而言之,自从我编写它以来,没有任何变化,只创建了新的 DbContext API,它仍然位于旧 API 之上。到目前为止,我看到的关于这个主题的最好描述是在《编程实体框架:DbContext》一书中。
归档时间: |
|
查看次数: |
4161 次 |
最近记录: |