1

I have created the POCO class and it's equivalent in edmx file (Category entity with only one way navigation property Parent)

public class Category {
    public int ID {get;set;}
    public string Name {get;set;}
    public Category Parent {get;set;}
} 

And I have an issue with CRUD operations affecting Parent property:

Retrieve looks like:

public void CanRetrieve() {
var category = context.Categories.Where(x => x.ID == id).FirstOrDefault();
cotext.LoadProperty<Category> (category, c => c.Parent);

}

ant is working fine (i get Category object with Parent property filled)

Add looks like:

public void CanAdd() {
    Category cat = new Category();
    cat.Name = "cat 1";    
    cat.Parent = new Category() {ID = 12}; //assuming that in the database there is a record with ID 12 
    context.Categories.Attach(cat);
    context.SaveChanges();
}

Is also working fine (in the DB new record appears with Parent_ID field set to 12)

And Update:

public void CanUpdate() {
    Category cat = new Category();
    cat.Name = "cat 1";    
    cat.Parent = new Category() {ID = 12}; //assuming that in the database there is a record with ID 12 
    context.Categories.Attach(cat);
    //XXX    
    context.SaveChanges()
}

does anything. If I replace the //XXX line with the following line:

Context.ObjectStateManager.ChangeObjectState(cat, EntityState.Modified); 

the value of Name property is updated form the source object (I guess other scalar properties would also be) but the Parent is ignored and the Parent_ID field in the base is preserved.

My question is: How in this scenario can I tell the context I want the Parent property value also reflected to the database and can it be done without passing all the values of Parent property (only an ID, just like in Adding scenario)?

Best regards,

Andrzej

2 Answers2

0

Unfortunately, I had to add the ParentId (or whatever is the name of the column) property to make it work. I know it sucks, but I didn't figure it out other way.

So, change the property and null the parent property, attach the instance to the context, mark it as modified and call SaveChanges(); and that's it.

IMO, this should be resolved by EF. I use EntityTypeConfiguration for each Class<->Table Mapping in order to keep the database and classes standard unchanged, so it should be straight forward to know that what I marked as primary key is what the EF must use.

apaderno
  • 28,547
  • 16
  • 75
  • 90
0

Are you really sure that your CanAdd code really works? You are attaching two new objects to context which means that they are in unchanged state. By calling SaveChanges they should not be inserted. If you use AddObject instead of Attach both new and parent categories will be set to Added state and both will be inserted in SaveChanges.

Your CanUpdate method doesn't work because you are just setting updated category to modified state but you have attached three objects - category, parent category and relations between them. You also have to change state of the relation.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • You are right, I was chopping the code in a little haste, so I've accidentally put Attach instead of AddObject to the CanAdd method. Sorry for the mislead. As for CanUpdate, as I uderstand I cannot set relationship state to Modified, doeas it mean in my scenario I have to remove the old relationship (change it to Deleted) and then put the new Parent entity and set relationship to Added)? – Andrzej Dajnowski Dec 06 '10 at 14:22
  • I guess yes because relation is defined by related entities. – Ladislav Mrnka Dec 06 '10 at 14:45
  • 1
    I have the same problem, but I can't figure how to change the state of the _relation_. Can you add an exemple? – Johnny5 Dec 05 '12 at 16:14