1

I have an email service which stores email requests in a database (due to legacy reasons). There are two entities, an EmailRequest

public class EmailRequest
    {
        [Key]
        public Guid ID { get; set; }
        public bool Sent {get; set;
        //Other props
        public virtual List<Attachment> Attachments { get; set; }
    }

And Attachments for a given email

public class Attachment
{
    [Key]
    public Guid Id { get; set; }
    //Other props
    public virtual EmailRequest EmailRequest { get; set;}

}

Insertions in to the DB are working fine – the email record goes in the ‘parent’ table and zero-to-many attachments are inserted in the attachments ‘child’ table. When the email has been sent I want to update the Sent flag in the parent table and delete any attachments as they are just wasting space. However, in my DBContext class when I call

Attachments.RemoveRange(Attachments.Where(a => a.EmailRequest.ID == identifier));

All the attachments are deleted but the parent (EmailRequest) is also being deleted. Any ideas what is causing this? I’ve turned off cascade deletions which did nothing as I suspected, as I’m deleting a child record, not a parent. However, I don’t know how to tell Entity Framework (6.1.3) not to delete the parent.

Any ideas?

EDIT

So as suggested in the comments, it doesn't look like EF itself is performing the delete, becuase if I go into SSMS and delete from the attachments table, its also deleting the parent. Must be something in the entity here.

EDIT 2

So if I use request.attachments.clear() instead of Attachments.RemoveRange() it clears the parent down (and the foreign key reference in Attachment) but leaves the attachment, so the exact opposite of what I want to do!

LDJ
  • 6,896
  • 9
  • 52
  • 87
  • 1
    I seriously doubt EF is doing this. Are you sure you don't have some trigger in the database on the `Attachment` table or something that may be responsible? One way to confirm if EF is responsible or not is by logging the SQL being executed by EF: https://msdn.microsoft.com/en-us/library/dn469464.aspx, and then you can see if it's generating a `delete` statement on `EmailRequest`. – sstan Aug 10 '16 at 14:24
  • I think setting `Attachments` to `new List<>` or using `Attachments.Clear()` works, but it just removes the keys on the children – Callum Linington Aug 10 '16 at 14:24
  • 1
    I can't replicate your issue, if I try all that the "parent" doesn't get deleted.... I wonder if it is because of that `virtual EmailRequest` property, causing it remove those relations... – Callum Linington Aug 10 '16 at 14:27
  • Also, you haven't shown how the foreign key relationship is configured in your EF entities. Maybe you did something wrong there? Still, I'm very skeptical that the problem has anything to do with EF. – sstan Aug 10 '16 at 14:37
  • http://stackoverflow.com/questions/17723626/entity-framework-remove-vs-deleteobject – umer Aug 10 '16 at 15:26
  • I dont see any foreign key column in your Attachments Table, or there would be a property with that property name in your Attachment Class. On which column you have made this relation. – umer Aug 10 '16 at 15:39
  • Are you utilizing `OnModelCreating`? or extra code to delete Email request under certain conditions? – Balah Aug 10 '16 at 15:46
  • @Balah no, nothing. all I have is a call to base.OnModelCreating(modelBuilder) – LDJ Aug 11 '16 at 05:45
  • @CallumLinington I've removed that from the attachment class and its made no difference to the behaviour in any way that I can see. I'll leave that out for now but the problem remains the same. – LDJ Aug 11 '16 at 06:14
  • @sstan nothing like that, no. The DB and tables are created through EF Migrations – LDJ Aug 11 '16 at 06:15
  • @umer the relationship is in the EmailRequests entity, which has a virtual property linking to attachments public virtual List Attachments { get; set; } – LDJ Aug 11 '16 at 06:18
  • what is your foreign key in your attachment table ? – umer Aug 11 '16 at 06:21
  • @umer In the migration script generated by EF, it adds: .ForeignKey("dbo.EmailRequests", t => t.EmailRequest_ID) – LDJ Aug 11 '16 at 06:28
  • There should be an EmailRequest_ID column as a foreign key in your Attachment table which relates to the ID column in EmailRequests Table. And there should be an EmailRequest_ID property in your Attachment Class. Then you can simply remove the Attachments with a particular EmailRequest_ID – umer Aug 11 '16 at 06:30
  • @umer tried explicitly adding the property but the behaviour is the same. Deleting the attachment also deletes the EmailRequest – LDJ Aug 11 '16 at 06:46
  • @LDJ apart from the Linq , if you have to query your data with simple sql, how would you fetch the attachments with a particular Email Request. Lets say how would you select all attachments where email request id =1 ? – umer Aug 11 '16 at 06:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120666/discussion-between-umer-and-ldj). – umer Aug 11 '16 at 07:37

1 Answers1

0

If you can see the difference I am first grabbing the parent entity and then deleting his child collections. where as you are deleting the child entities directly. I cant see how the parent entity would be deleted in this instance since it is sitting right there in memory for you to see. if it does then I would check my DB constraints big time to see if entity framework has added an unwanted constraint.

using (var context = new MyContext())
{
    var parent = context.Parents.Include(p => p.Children)
    .SingleOrDefault(p => p.Id == parentId);

    foreach (var child in parent.Children.ToList())
    context.Children.Remove(child);

    context.SaveChanges();
}

I'm hoping the method above gives you more debugging options or just eliminates the issue. I'm also adding a link to let you check the SQL generated by Entity Framework for more debugging options (see below)

How do I view the SQL generated by the Entity Framework?

Community
  • 1
  • 1
  • See Edit2 above. If I do that, it deletes the parent and leaves the child! :s – LDJ Aug 11 '16 at 06:17
  • I'm not trying to argue I just want to make sure you actually attempted the code above. If you can see the difference I am first grabbing the parent entity and then deleting his child collections. where as you are deleting the child entities directly. I cant see how the parent entity would be deleted in this instance since it is sitting right there in memory for you to see. if it does then I would check my DB constraints big time to see if entity framework has added an unwanted constraint. – Charles McIntosh Aug 11 '16 at 13:40