Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Deleting parent and child like the following does work for me. The children are deleted <em>before</em> the parent and it is a single database roundtrip (one call to <code>SaveChanges</code>) with of course three DELETE statements in a single transaction:</p> <pre><code>using (var ctx = new MyContext()) { var parent = ctx.MyEntities.Include(e =&gt; e.Children).FirstOrDefault(); foreach (var child in parent.Children.ToList()) ctx.MyEntities.Remove(child); ctx.MyEntities.Remove(parent); ctx.SaveChanges(); } </code></pre> <p>(Using <code>ToList()</code> is necessary here because calling <code>Remove</code> for the children also removes from the parent's <code>Children</code> collection. Without using <code>ToList</code> a runtime exception would be thrown that the collection the <code>foreach</code> loop is iterating over has been modified.)</p> <p>The order in which <code>Remove</code> is called for children and parent doesn't matter. This works as well:</p> <pre><code>using (var ctx = new MyContext()) { var parent = ctx.MyEntities.Include(e =&gt; e.Children).FirstOrDefault(); var children = parent.Children.ToList(); ctx.MyEntities.Remove(parent); foreach (var child in children) ctx.MyEntities.Remove(child); ctx.SaveChanges(); } </code></pre> <p>EF sorts the DELETE statements in the correct order in both cases.</p> <p>Full test program (EF 5 / .NET 4.5 / SQL Server):</p> <pre><code>using System.Collections.Generic; using System.Data.Entity; using System.Linq; namespace EFSelfReference { public class MyEntity { public int Id { get; set; } public string Name { get; set; } public int? ParentId { get; set; } public MyEntity Parent { get; set; } public ICollection&lt;MyEntity&gt; Children { get; set; } } public class MyContext : DbContext { public DbSet&lt;MyEntity&gt; MyEntities { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity&lt;MyEntity&gt;() .HasOptional(e =&gt; e.Parent) .WithMany(e =&gt; e.Children) .HasForeignKey(e =&gt; e.ParentId); } } class Program { static void Main(string[] args) { Database.SetInitializer&lt;MyContext&gt;( new DropCreateDatabaseAlways&lt;MyContext&gt;()); using (var ctx = new MyContext()) { ctx.Database.Initialize(false); var parent = new MyEntity { Name = "Parent", Children = new List&lt;MyEntity&gt;() }; parent.Children.Add(new MyEntity { Name = "Child 1" }); parent.Children.Add(new MyEntity { Name = "Child 2" }); ctx.MyEntities.Add(parent); ctx.SaveChanges(); } using (var ctx = new MyContext()) { var parent = ctx.MyEntities.Include(e =&gt; e.Children) .FirstOrDefault(); foreach (var child in parent.Children.ToList()) ctx.MyEntities.Remove(child); ctx.MyEntities.Remove(parent); ctx.SaveChanges(); } } } } </code></pre> <p>Screenshot after the first <code>using</code> block with current content in DB table before the entities are deleted:</p> <p><img src="https://i.stack.imgur.com/GqALe.png" alt="screen 1"></p> <p>Screenshot from SQL profiler after the last <code>SaveChanges</code>:</p> <p><img src="https://i.stack.imgur.com/t7jpI.png" alt="screen 2"></p> <p>I.e. <code>Child 1</code> (Id = 2) and <code>Child 2</code> (Id = 3) are deleted <em>before</em> <code>Parent</code> (Id = 1).</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload