Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert new object with existing object

I am new to EF 4 and this is what I have done so far:

  • Create an edmx file based on my database
  • Create a code generation for my objects (POCO). Now I have a model1.tt, when expanded I see al my classes
  • Create a repository for each class, based on IRepository

Now, I am working with two objects, A and B. Object A has a property of type B. In my winform I have a combo filled with objects of type B. When the save button is pressed, a new instance of class A is created and all the properties are set. The object B property is set as follows:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem;

Then I create a repository for objectA and call the save method. In this save method I have this code±

public bool Save(ObjectA obj)
{
  using(MyContext context = new MyContext())
  {
    context.objectAs.AddObject(obj);
    context.SaveChanges();
  }
}

This code, does save a new entry to the database, but it is also creating a new record for object B! I don't want this, because object B already exists in the database! (I have selected this one from the combobox).

This is how I fill my combobox:

In the objectB repository:

public IList<ObjectB> GetAll()
{
    using(MyContext context = new MyContext())
    {
        IList<ObjectB> objects = context.objectBs.ToList();
        return objects;
    }
}

In my form:

ObjectBRepository rep = new ObjectBRepository();
IList<ObjectB> objects = rep.GetAll;

cmbBObjects.Datasource = objects;
// etc..

So my question is, what do I have to do to save object A without creating a new record for objectB?

like image 309
Martijn Avatar asked Mar 24 '11 08:03

Martijn


2 Answers

If you don't want insert objectB you must inform EF about it. When you call context.objectAs.AddObject(obj) for objectA you are saying: I want to insert objectA and all its dependencies. But obviously you don't want to save dependecies so you must either:

  • Load objectB from DB before adding it to objectA. In such case EF will know that objectB is existing object and it will not insert it again.
  • Attach objectB to context before adding it to objectA. ObjectB will be handled as existing but unchanged.
  • Set the state of objectB after inserting objectA. You can do that by calling: context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged)

Example of the fist suggestion:

var id = objectB.Id;
objectA.myObjectB = context.ObjectBs.SingleOrDefault(o => o.Id == id);

Example of the second suggestion:

context.ObjectBs.Attach(objectB);
objectA.myObjectB = objectB;

Example of the third suggestion:

objectA.myObjectB = objectB;
context.ObjectAs.AddObject(objectA);
context.ObjectStateManager.ChangeObjectState(objectB, EntityState.Unchanged);
like image 56
Ladislav Mrnka Avatar answered Nov 04 '22 22:11

Ladislav Mrnka


I suppose that problem in following row:

objectA.myObjectB = (objectB)cmbBObjects.selectedItem;

Because of result (objectB)cmbBObjects.selectedItem detached from datacontext entity framework create new instance. Instead this you can:

1.Assign objectB id to objectA

var b = (objectB)cmbBObjects.selectedItem;
objectA.myObjectBId = b.Id;

2.Or load objectB from dataContext and than assign to objectA:

var b = (objectB)cmbBObjects.selectedItem;
var dcB = context.ObjectBs.Single(x=> x.Id == b.Id);
objectA.myObjectB = dcB;

Just try my suggestions and come back with results, because i don't know exactly.

Hope this help.

like image 38
Andrew Orsich Avatar answered Nov 04 '22 22:11

Andrew Orsich