26

How do I set up my domain and the LINQ statement so I can delete a record from a database?

public class Category    {
    public int CategoryId { get; set; }
    public string Name { get; set; }

    public List<Product> Products{ get; set; }

}
public class Product {
    public int ProductId { get; set; }
    public string Name { get; set; }

    public int CategoryId {get; set; }
    public Category Category{ get; set; }
}

What I'd like to do is delete Category and be able to cascade the delete to all the child products.

  1. Is there any other additional attributes needed in my domain?
  2. What is the LINQ statement to delete objects without doing a round trip? (I do not want to select, just a direct delete).

Is this the only way to do this?

Category category = new Category() {  CategoryId = 1   } ; 
context.AttachTo("Category", category);
context.DeleteObject(category);
context.Savechanges();

2 Answers 2

41

You mentioned EF code first which means EF 4.1 but you have shown example of deleting object in EF 4. Correct approach to delete object in EF 4.1 without loading it from database is:

var category = new Category() { CategoryId = 1 };
context.Categories.Attach(category);
context.Categories.Remove(category);
context.SaveChanges();

If you didn't change anything in configuration of defalut conventions it will also delete all related products because OneToManyCascadeDeleteConventions ensures that all one-to-many relations are created with ON CASCADE DELETE. There will be no additional roundtrips to database - only single DELETE statement for Category with Id = 1.

The different situation can occure if you want to delete fully loaded Category (with loaded Products navigation property) in such case EF will create separate delete statement for each Product so you will have N+1 roundtrips to database where N is number of products in category. Here is how cascade delete works in EF. It is related to entity designer but described principles are the same.

Sign up to request clarification or add additional context in comments.

9 Comments

+1 You are a godsend at the moment for me! Your answers seem to keep coming up on top of Google when searching for EF issues!.... RE: Your last paragraph - If I have an object which has a virtual property (a list) which has not been accessed/lazy loaded, and I have cascade delete on, will it send the one delete command, or will it then load the virtual property and then send multiples?
@William: It should delete them without loading because deletion is handled by cascade delete in the database.
This has never worked for me in EF4.1, 4.3, or 5.0. Attempting to delete an EF Code First entity this way with one-to-many children consistently gets me the Exception: The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.ChildTable_dbo.ParentTable_Parent_Id". The conflict occurred in database "Database", table "dbo.ChildTable", column 'Parent_Id'. The statement has been terminated.
@Chirs: It means that your database doesn't have cascade delete defined on relationships. EF's ability for cascade delete is dependent on cascade delete configured in the database.
@ChrisMoschini I too was coming up against this issue with EF 6.1.1 I found that adding the [Required] attribute to parent reference in the child class, got the delete cascade working for me.
|
3

Taken from the VS2010 auto generated code:

Category category = db.Categories.Find(id);
db.Categories.Remove(category);
db.SaveChanges();

2 Comments

how come I don't have the method Remove?
You should have it here as the "db.Categories..." is of type DbSet<T>, which has the Remove method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.