How to gracefully bind a POCO Entity Framework 5 structure and save it?

I am making an MVC4 web application using Entity Framework 5 (first databases with created POCOs) to access data.

In the application, the user views several screens, creating or editing a document (called a “case study”). When they come to the final screen, their document exists as CaseStudy POCO in memory, and everything is fine, until it's time to save this structure in the database.

To save the document, I defined several database tables, which, in turn, are mapped to the EF POCOs used by the business layer, which is then consumed by the MVCs. Thus, short-term DbContexts are used to retrieve POCOs and store them in a session between requests.

As a result, the save screen should save the contents of this POCO, which has navigation properties, to existing tabular data (tables of categories, layouts and sections), as well as added or updated data (CaseStudySections and CaseStudy itself). Thus, all POCOs are either new, or the context used to retrieve them has long been disposed of. In other words, they are all “suspended.”

What is unusual in this article is that I already have a working solution. The problem is that it is bulky, fragile and inelegant. I am posting the code below. Pay attention to iteration through subcategories, explicit addition and attachment, you need to get the recording object and mark individual properties as changed so that they are updated, and a terrible song and dance at the end to collect an assembly of additional materials. If this is what is required to work with individual POCOs in EF5, I will be disappointed.

Am I missing something? Is this consistent with best practices? Is there a more graceful and / or compressed way to attach a POCOs structure and insert / update?

Code to save case study:

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();
}
+5
source share
2 answers

, , . EF , . , , , , .

, - - , , API DbContext, API. , , Entity Framework: DbContext.

+3

, :

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

db.

+2

All Articles