Hugo
Hugo

Reputation: 2185

Save entity with child entity

I'm struggling with this for a couple days now and I need a little help. I also do many searches over Google and StackOverFlow, but did not find a solution.

I'm trying, what I believe, is something simple but I can't get i to work.

Using EntityFramework I'm changing a record from a table named "tblAnneeFinanciere", and also I'm adding child record in "tblAnneeFinanciere.tblPeriodeFinanciere" from is NavigationPropoerty. But I can't get the SaveChanges context method to save all information.

I've try some different scenario, just to reach different error.

Here my code snippet

 Public Sub Test()
        Dim AnneesFine = New List(Of tblAnneeFinanciere)

        Using database = Informat.WPF.EF.MaitreDBEntities.GetEFConnections()

            Dim query = From data In database.tblAnneeFinanciere
                        Where data.ID = 7
                        Select data


            AnneesFine = query.ToList
        End Using

        Dim ChangedAnneeFina = AnneesFine.First
        ChangedAnneeFina.Descr = Date.Now.ToLongDateString
        ChangedAnneeFina.Poincon = Date.Now

        Dim addedRecord = New tblPeriodeFinanciere() With {
                                                            .ID = 1,
                                                            .Descr = "Test#1",
                                                            .DescrEn = "Test#1",
                                                            .NoPeriode = 10,
                                                            .pCieID = ChangedAnneeFina.CieID.Value,
                                                            .DateDebut = Date.Now,
                                                            .DateFin = Date.Now,
                                                            .pAnneeFinanciereID = ChangedAnneeFina.ID,
                                                            .Poincon = Date.Now
                                                        }

        ChangedAnneeFina.tblPeriodeFinanciere.Add(addedRecord)

        Using database = Informat.WPF.EF.MaitreDBEntities.GetEFConnections()
            ''*************************************************************
            ''First attempt
            Dim obj = database.GetObjectByKey(ChangedAnneeFina.EntityKey)
            obj = ChangedAnneeFina

            ''*************************************************************
            'Second attempt

            database.tblAnneeFinanciere.ApplyCurrentValues(ChangedAnneeFina) ' Value are correctly applied
            database.SaveChanges() '' Saving tblAnneeFinanciere work correctly but child table 'tblPeriodeFinanciere' is not updated

            '*************************************************************
            'third attempt
            ' database.tblAnneeFinanciere.ApplyCurrentValues(ChangedAnneeFina) ' Value are correctly applyed
            Dim obj2 = database.GetObjectByKey(ChangedAnneeFina.EntityKey)
            obj2 = ChangedAnneeFina

            database.tblPeriodeFinanciere.AddObject(ChangedAnneeFina.tblPeriodeFinanciere.First)

            '*************************************************************


            database.SaveChanges()

        End Using


    End Sub

What I do wrong, which way should I go?

My working environment is

Windows 7; Visual Studio 2013; Target framework version : 4.0; EntityFramework version : 4.1

Upvotes: 0

Views: 267

Answers (1)

JotaBe
JotaBe

Reputation: 39025

When you're using EF in a multilayered application, the Entity is taken out of the context that usually tracks its changes.

I.e. if you're withing a context, and modify a property, and add children to it, the context tracks this changes, and SaveChanges knows what to do.

But, when you have a multilayered app, the entity is taken out of the context.

What you need to do is track the changes yourself. And, then you have to instance a new context, attach the entity to the context, and set the state of the attached entity and all their children.

You can do two diferent things to attach the entty to the context:

  • adding the entity to its collection, using Add() will set the state of all entites to Added,and save changes will treat them all as if they were new
  • attaching the entity using Attach(). In this case you need to set the state of the entity so that save changes knows what to do.

Example of adding a disconected entity:

ctx.Set<TEntity>().Add(newEntity);
ctx.SaveChanges();

This would attach the whole tree as if all the objects were Added

Example of modifying a disconnected entity:

var attached = ctx.Set<TEntity>().Attach(changedEntity);
ctx.Entry(attached).State = EntityState.Modified;
ctx.SaveChanges();

This would attach the whole tree as if all the objects were Unchanged

Remember that you need to track the changes, and set them back after attaching the objects to the context.

Upvotes: 1

Related Questions