0

I'm using the Entity Framework 6, database first (I'm new to EF). I have two entity classes, Structure and Contour, where a Structure may contain multiple objects of type Contour. I would like to be able to remove Contours whether or not they already exist in the database. For example, if I add a new Contour to an existing Structure object like this:

Contour contour = new Contour
{
    Structure = structure,
};

I can delete it like this:

contour.Structure = null;

But if the contour already exists in the database and I delete it, saving the entity context throws the exception "The relationship could not be changed because one or more of the foreign-key properties is non-nullable..."

That exception tells me that the entity context wasn't aware that it's supposed to delete that Contour. My fix was to delete a Contour as follows:

contour.Structure = null;
EntityContext.Contours.Remove(contour);

But if the contour doesn't exist in the database already (because it was just added), then the entity context is not aware of it and it doesn't find it in its Contours list. So then I modified my delete method to this:

contour.Structure = null;
if (EntityContext.Contours.Local.Contains(contour))
{
    EntityContext.Contours.Remove(contour);
}

This appears to work so far, but is this how I'm supposed to delete entity objects that may or may not already exist in the database?

redcurry
  • 2,381
  • 2
  • 24
  • 38
  • 1
    The `contour.Structure = null;` doesn't remove neither the `contour` not the `structure`. It just tries to set the foreign key between them to NULL. The latter check is ok, instead you could possibly test whether the primary key has been set (`> 0`) if keys are autogenerated. – Wiktor Zychla Oct 02 '15 at 15:40
  • Yes, they're auto-generated, so I can test for what you suggested. Thanks. Since `contour.Structure = null;` doesn't delete it from the structure's `Contours` list, I guess that means I need to say `contour.Structure.Contours.Remove(contour)`? – redcurry Oct 02 '15 at 15:46
  • Have a [look at this](http://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro) – BBauer42 Oct 02 '15 at 15:50

2 Answers2

-1

Don't make it too complex, you may remove contour by simple call context.Contours.Remove(contour). It doesn't care is contour already in database or not. For example:

using (var context = new EntityContext())
{
    Vendor vendor = new Vendor();
    context.Vendors.Add(vendor);
    context.Vendors.Remove(vendor);
    context.SaveChanges();
}
Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
  • So I always need to add the `Contour` directly to `context.Contours`? I thought I could just set `contour.Structure = structure` where `structure` contains a list of `Contours`. – redcurry Oct 02 '15 at 16:03
  • 1
    @redcurry You can. However, when you set `contour.Structure = structure` it adds the Contour object to EF's tracking. When you set `contour.Structure = null` you are removing the link _but the Contour object is still being tacked_. You must then user `context.Contours.Remove()` to remove it from the tracking – Vlad274 Oct 02 '15 at 16:36
  • @redcurry, I disagree with @Vlad274. `contour.Structure = structure` doesn't add `contour` to tracking. If you call `context.Contours.Remove(contour);` after that, it throws the `InvalidOperationException`. Correct option is add contour to structure: `structure.Contours.Add(contour)` instead. – Ilya Chumakov Oct 02 '15 at 17:21
-1

Two options:

dbContext.Contours.Remove( contour );

or

structureInstance.Contours.Remove( contour ); // but this will load all of a structure's contours if not loaded already
Moho
  • 15,457
  • 1
  • 30
  • 31
  • The first options fails if `contour` is a newly created object that I added by setting its `Structure` property to an existing structure. Perhaps this is the wrong way to add entity objects. It seems like I need to add them directly to the context's `Contours` list. I'm guessing the same goes for the second option---it assumes that the `contour` was added to the `context.Contours` list, right? – redcurry Oct 02 '15 at 16:05