简体   繁体   中英

Saving changes to child collections with Entity Framework

I have made changes to an EntityCollection which is an object of another EntityCollection, and when I try to save those changes, I get the following error:

The EntityCollection has already been initialized. The InitializeRelatedCollection method should only be called to initialize a new EntityCollection during deserialization of an object graph.

Any ideas what I might be missing?

The following is the code I used.

public void UpdateCompanyManagement(Company newCompany)
{
    Company oldCompany = entities.Companies.Where(c => c.COM_ID == newCompany.COM_ID).SingleOrDefault();

    oldCompany.Managements = newCompany.Managements;

    try
    {
        entities.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
        entities.Refresh(RefreshMode.ClientWins, newCompany.Managements);
        entities.SaveChanges();
    }
}

I'm able to save the parent collection successfully, using the following code:

public void UpdateCompanyDetails(Company newCompany)
{
    Company oldCompany = entities.Companies.Where(c => c.COM_ID == newCompany.COM_ID).SingleOrDefault();
    entities.ObjectStateManager.ChangeObjectState(oldCompany.city, System.Data.EntityState.Modified);
    oldCompany = newCompany;

    try
    {
        entities.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
        entities.Refresh(RefreshMode.ClientWins, oldCompany);
        entities.SaveChanges();
    }
}

As far as I understand, you are effectively trying to change parent of elements in Management collection. EF has hard time trying to understand your intention.

Similar problems were answered here available here .

After much research, I found a problem in my database/model setup (since I'm using a legacy database). Most of the tables in my database had no Primary Key, and those that did, had no Identity Specification and this was causing problems. So I corrected the database and updated my model.

And, I eventually found a simple way to write clean EF code.

The code in both functions could be re-written as follows:

public void UpdateCompanyManagement(Company company, int mgmtID)
{
    var management = company.Managements.Where(m => m.M_ID == mgmtID).SingleOrDefault();

        management.name = "new name";
        management.position = "new position";

        // edit all you want, then save
        // no further code is required
        // except you've done something wrong somewhere

    try
    {
        entities.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
        entities.Refresh(RefreshMode.ClientWins, company);
        entities.SaveChanges();
    }
}

and also,

public void UpdateCompanyDetails(Company company)
{
    company.name = "new company name";
    company.address = "new company address";

    // edit all you want then save
    // no further code is required
    // except you've done something wrong somewhere

    try
    {
        entities.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
        entities.Refresh(RefreshMode.ClientWins, company);
        entities.SaveChanges();
    }
}

Thanks, Peter the Viking! :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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