0

I have the following two entity sets representing Dept & Emp:-

public partial class Dept
{
    public Dept()
    {
        this.Emps = new HashSet<Emp>();
    }

    public int DeptID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Emp> Emps { get; set; }
}


public partial class Emp
    {
        public int EmpID { get; set; }
        public string Fname { get; set; }
        public string Lname { get; set; }
        public int DeptID { get; set; }

        public virtual Dept Dept { get; set; }
    }

Now I wrote this test action method , which will try to delete a dept which have one Emp assigned to it, as follow:-

public ActionResult Test()
{
            Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
            Emp e = db.Emps.SingleOrDefault(a => a.id == 100);
            db.Entry(d).State = EntityState.Deleted;


            db.Emps.Remove(e);
            db.SaveChanges();
            return Content("done");
}

I thought that an exception will be raised when calling this action method, since the Dept with id=1 already has one emp with id=100. But what happened is that EF has removed the emp first, then the dept. As a final result the above action method, deleted both the dept with id=1 and emp with id =100.. so can you advice on this please? Bearing in mind that if I try to delete the Dept only as follows:

public ActionResult Test()
{
                Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
                //Emp e = db.Emps.SingleOrDefault(a => a.id == 100);
                db.Entry(d).State = EntityState.Deleted;

                //db.Emps.Remove(e);
                db.SaveChanges();
                return Content("done");
}

I will get the following exception:-

The DELETE statement conflicted with the REFERENCE constraint \"FK_Emp_ToTable\". The conflict occurred in database \"C:\USERS\...\DOCUMENTS\VISUAL STUDIO 2013\PROJECTS\WEBAPPLICATION19\WEBAPPLICATION19\APP_DATA\DATABASE1.MDF\", table \"dbo.Emp\", column 'DeptID'.\r\nThe statement has been terminated."}

So can anyone advice on how EF is implementing these scenarios?

EDIT

i check the sql profiler for my action method and i noted the following 2 delete sql statments:-

exec sp_executesql N'delete [dbo].[Emp]
where ([EmpID] = @0)',N'@0 int',@0=100

exec sp_executesql N'delete [dbo].[Dept]
where ([DeptID] = @0)',N'@0 int',@0=1

so it have deleted the emp first then the dept,, so how EF determine the order , you mentioned it is smart enough to know ,, but what govern this behavior ?

John John
  • 1
  • 72
  • 238
  • 501

1 Answers1

1

You tried to delete a Dept which has a collection of Emp assigned to it.

The following exception occurred

The DELETE statement conflicted with the REFERENCE constraint

That means that there's a constraint to the Dept - Emp relationship. My guess is that it's an one - to many relationship, with one Dept being optional to Emp.

I can tell it's optional because the foreign key DeptID is a Nullable<int>.

When you try to delete a Dept, you get an exception because dept is referenced in Emp.

In the first action method you deleted by primary key

    Dept d = db.Depts.SingleOrDefault(a=>a.id ==1);
    Emp e = db.Emps.SingleOrDefault(a => a.id == 100);

And then used db.Emps.Remove(e); to mark the relationship between as deleted. If the relationship was optional, Emp would be set to Null using only an SQL Update.

In your case i see two SQL Delete statements were called The relationship is therefor identifying.

When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. In an identifying relationship the dependent entity cannot exist without the principal entity. This constraint causes the following behaviors in an identifying relationship:

Deleting the principal object also deletes the dependent object. This is the same behavior as specifying in the model for the relationship.

Removing the relationship deletes the dependent object. Calling the Remove method on the EntityCollection marks both the relationship and the dependent object for deletion.

GMich
  • 567
  • 4
  • 11
  • i think your reply is not related to my question. there is not any cascade delete, because if i try the second action method an exception will be raised,, so how come there is a cascade delete with an exception!!! – John John Dec 22 '14 at 00:12
  • and my main question is not about the exception, is about how the first action method did not raise any exception !!1 – John John Dec 22 '14 at 00:13
  • Thanks for the reply, yes the relation between emp and dept is optional, as mentioned on my entity classes, so the Emp.DeptID inside the sql server is of type nullable. but still i can not understand the problem, as i know that my first action method will be translated into two delete statemts inside the database. the first statement will be "Delete from Dept where DeptID = 1" and the second statement will be "Delete from Emp where EmpID= 100". now the first delete statement should raise an exception , but this was not the case when using EF ? can you adivce ? – John John Dec 22 '14 at 11:23
  • so my question is what govern how EF determine the order of the deletion ? can you check my edit section inside my original question,, thanks... – John John Dec 22 '14 at 12:21
  • you mentioned the following rule "When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. I" , but in my case this does not apply, as the deptid is not part of the emp primary key,,, i can not understand you reply, can u exaplin it more ? – John John Dec 22 '14 at 14:31
  • but we are building an assumption that "When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. I"" and this DOES NOT APPLY in my case ,,,, the DeptID inside the emp table is FK and not part of the primary key inside the emp table...... – John John Dec 22 '14 at 15:05
  • not sure what you are trying to explain ? the relation between Dept and Emp is managed by an optional FK inside the emp table... and not inside a many-to-many table. so an Emp can exists even if it does not have a dept and of course i dept can exists without being referenced by an Emp table... – John John Dec 22 '14 at 15:06
  • Its cascade deleting... EF knows the order of deletion. First the collection of Emps (depended) inside Dept get deleted and then the Dept (principal) – GMich Dec 22 '14 at 15:27
  • By deleting only the principle (Dept), the Emp collection won't get cascade deleted because their relationship is optional – GMich Dec 22 '14 at 15:36
  • so what you are trying to say, is that EF before deleting the dept will check to see if any EMP is loaded or not , and in my case it will see that the EMP is marked for deletion so it decided to first delete the Emp then the Dept ... sound really strange!! sometimes you need features inside EF which you can not find, and on other scenarios you expect EF to raise exceptions then you find that it is smart enough not not raise an exception and find the correct order of execution... i am still confused about this!!! – John John Dec 22 '14 at 15:53
  • there is something missing which i am unable to understand,,, in my case the logic should say when you try to delete Dept which have emp should raise exception,,, but as i also specify that i want to remove the Emp , then EF re-order the delete sql statements to make the deletion possible... but not sure what are the rules inside EF that govern this.... it does not have to do if the relation is optional or not. – John John Dec 22 '14 at 16:00
  • 2
    That's how it works. If you want to delete the principle, it'll first look if the depended is marked for deletion. If cascade delete was enabled this wouldn't be a problem. By only deleting the principle, the depended would get deleted as well. – GMich Dec 22 '14 at 16:01
  • so can i define the following rule when you want to delete a Principle object; EF will check first to see if all its dependencies are marked for deletion,, if so it will delete all the dependencies then it will proceed with deleting the Principle. is this correct? – John John Dec 22 '14 at 16:13
  • where i can find a full documentation about EF's scenarios for deleting, adding, updating entityies? – John John Dec 22 '14 at 16:34