0

I have the following code:

public class Parent
{
  public int ParentId {get;set;}
  public ICollection<Child> Children {get;set;}
}

public class Child
{          
  public int ChildId {get;set;}
  public Parent Parent {get;set;}
}

It's mapped as one-to-many by EF without any additional efforts. When I replace Children with new collection (with 3 another items) I have old orphan entities in child-table like this:

Id | Parent_Id
1     NULL       <-- orphan
2     NULL       <-- orphan
3     NULL       <-- orphan
4       1        <-- new
5       1        <-- new
6       1        <-- new

I want to get rid of them with identifying relationship explicitly:

modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);

But I don't have ParentId property in children. I have only "Parent" pointing directly to the parent entity. If I try

modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.Parent });

I get an error message:

The property ... cannot be used as a key property on the entity ... because the property type is not a valid key type

Is there any way remove all unnecessary orphans?

Roman Pushkin
  • 5,639
  • 3
  • 40
  • 58

2 Answers2

1

As far as I know for identifying relationship you will need the parents primary key contained as part of the primary key of the child. EF will then allow you to remove the child from collection and delete it for you.

Just having the navigation property won't work. Identifying relationships are a DB level concept so needs an exposed Primary key id

See my question here on that subject

Community
  • 1
  • 1
GraemeMiller
  • 11,973
  • 8
  • 57
  • 111
1

In my application I have a similar model. However, instead of removing orphans I do not produce them. If I want to remove some child objects I do it in the following way:

//This line attaches a parent object to the session. EF will start monitoring it. 
Entry(parent).State = EntityState.Modified;

//This code is responsible for finding children to delete.
foreach (var child in parent.Children.Where(ch => ch.Deleted))
    //This line says EF that given child should be removed.
    //This line also causes that an object will be removed from Children collection.
    Entry(child).State = EntityState.Deleted;

SaveChanges();

Deleted is a property which I set to true if I want to delete an object.

Michał Komorowski
  • 6,198
  • 1
  • 20
  • 24