繁体   English   中英

如何优雅地重新连接并保存实体框架5 POCO结构?

How do I gracefully reattach an Entity Framework 5 POCO structure and save it?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在使用Entity Framework 5(数据库优先生成生成的POCO)制作MVC4 Web应用程序以进行数据访问。

在该应用程序中,用户浏览多个屏幕,创建或编辑文档(称为“案例研究”)。 当他们到达最后一个屏幕时,他们的文档以CaseStudy POCO的形式存在于内存中,并且一切都很好,直到需要将该结构保存到数据库中为止。

为了存储文档,我定义了几个数据库表,这些表又映射到业务层使用的EF POCO,然后由MVC控制器使用。 这样,短暂的DbContext用于检索POCO,并将它们存储在请求之间的会话中。

结果,保存屏幕必须将该具有导航属性的POCO的内容保存到现有表数据(Category,Layout和Sections表),以及添加或更新的数据(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();
}
2 个回复

通常,这是您必须要做的。 附加分离的对象图时,必须将要执行的每个更改告知EF。 我并不是说您的代码无法简化,但是如果您要添加或修改它,您仍然必须处理每个实体并设置其状态。

是关于该主题的较旧但仍然有效的答案-简而言之,自从我编写它以来,没有任何变化,仅创建了新的DbContext API,该API仍位于旧API的顶部。 到目前为止,我对这个主题的最佳描述是在《 编程实体框架:DbContext》一书中

怎么做:

db.CaseStudies.Attach(caseStudy);
db.Entry(caseStudy).State = EntityState.Modified;
db.SaveChange();

这会将模型中的所有更改保存到数据库。

1 如何将Entity Framework与现有数据库和Poco结构一起使用

在过去的几天里,我一直在重构和使用C#编写的我现有的应用程序来使用Entity Framework而不是我制作的自定义数据访问层。 一切顺利,直到我遇到一个特定的POCO。 这个POCO有6个属性,其中4个属于基本类型,但最后2个给我带来麻烦,因为它们是其他现有的POCO。 这给我带来 ...

5 如何调整Entity Framework POCO T4模板以在单独的项目中创建类?

我喜欢先保留我的代码 - 或者生成T4 - 将项目中的POCO与DbContext分开。 这有助于确保我的实体类不会耦合到任何一个数据访问服务。 当我创建一个新的DB第一个EDMX模型时,向导会生成一个T4模板,以在与DbContext相同的项目中生成所有POCO。 如何修改此模板以将 ...

6 实体框架-分离对象并重新连接

我必须在数据库中插入几个实体,其中包含对数据库中已经存在的其他实体的引用,例如: tmpPosition-Object是从另一个上下文中获取的,因此,在将对象插入数据库时​​,我必须将tmpPosition-Object与先前的上下文分离。 遗憾的是,之后无法再访问tmpPosit ...

2013-10-08 13:31:30 0 229   c#/ entity
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM