30

I would like to know how to delete an object from Entity Framework 4.1 without first having to load the object from the database. I have found these other 2 answers on Stack Overflow, but they do not pertain to EF 4.1

I have tried the following code but it does not work

public void DeleteCar(int carId)
{
  var car = new Car() { Id = carId };
  _dbContext.Cars.Attach(car);
  _dbContext.Cars.Remove(car);
  _dbContext.SaveChanges();
}

I want to avoid the code below.

public void DeleteCar(int carId)
{
  var car = context.Cars.Find(carId);
  _dbContext.Cars.Remove(car);
  _dbContext.SaveChanges();
}

And I do not want to call a stored procedure or execute raw sql.

Community
  • 1
  • 1
Paul
  • 18,349
  • 7
  • 49
  • 56
  • 1
    The first example works. You are doing something wrong elsewhere. – Ladislav Mrnka Aug 04 '11 at 22:05
  • 1
    Ladislav Mrnka, can you provide an example project showing how it works for you. It doesn't work for me. – Paul Aug 05 '11 at 03:19
  • 1
    I agree with @Ladislav: The first code snippet must work. Do you get an exception? And which one? Or does it silently fail to delete anything? Do you have a composite primary key in the Car class? Is there a constraint perhaps in the DB which doesn't allow to delete the car? – Slauma Aug 05 '11 at 20:12
  • @Slauma, do you have an example app that shows that it works? I agree it should work, but it's not. I do not have a composite primary key. It's just a regular int. – Paul Aug 08 '11 at 14:51
  • @Paul: The example, I would provide, is **exactly your first code snippet**. What does it mean that it "does not work"? Do you get an exception? – Slauma Aug 08 '11 at 15:11
  • 1
    @Slauma it does not work because it doesn't delete the row from the database. It does not throw an exception nor does it delete the row – Paul Aug 16 '11 at 13:13
  • 2
    provide some more code, like your DbContext class and the entity – agradl Aug 16 '11 at 14:58

4 Answers4

40

I use the following for my deletes, works great.

public virtual ActionResult Delete(int commentID)
{
    var c = new Comment(){CommentID = commentID};
    db.Entry(c).State= EntityState.Deleted;
    db.SaveChanges();
    return RedirectToAction(MVC.Blog.AdminComment.Index());
}

enter image description here

agradl
  • 3,536
  • 2
  • 18
  • 16
10

Just to convince you that your first code snippet must work here is a simple example you can copy, paste and test:

  • Create a new console application project (.NET 4)
  • Add reference to EntityFramework.dll (EF 4.1)
  • Delete the content of Program.cs and paste in the following:

->

using System.Data.Entity;

namespace EFDeleteTest
{
    public class Car
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<Car> Cars { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Database with name "EFDeleteTest.MyContext"
            // will be created automatically in SQL Server Express

            int carId = 0;
            using (var context = new MyContext())
            {
                var car = new Car { Name = "Test" };
                context.Cars.Add(car);
                context.SaveChanges();

                carId = car.Id;
            }
            //Make breakpoint here and check that the car is indeed in the DB

            using (var context = new MyContext())
            {
                var car = new Car() { Id = carId };
                context.Cars.Attach(car);
                context.Cars.Remove(car);
                context.SaveChanges();
            }
            //Make breakpoint here and check that the car
            //indeed has been deleted from DB
        }
    }
}

If you have a SQL Server Express DB it will automatically create the DB.

Perhaps this might help you to compare with your code because it looks as if something not visible in your code fragments is causing the different behaviour you describe.

Slauma
  • 175,098
  • 59
  • 401
  • 420
3

use stub entities:

public void DeleteCar(int carId)
{
  var car = new Car() { Id = carId };
  _dbContext.AttachTo("Cars",car); 
  _dbContext.DeleteObject(car); 
  _dbContext.SaveChanges();
}

reference:

http://blogs.msdn.com/b/alexj/archive/2009/06/19/tip-26-how-to-avoid-database-queries-using-stub-entities.aspx

Juan Jimenez
  • 5,812
  • 6
  • 28
  • 37
  • 1
    The code snippet does not work with Entity Framework 4.1. Entity Framework 4.1 does not have AttachTo() or DeleteObject() – Paul Aug 08 '11 at 14:50
  • then, as @Ladislav Mrnka said, your first example should work, is the same using another syntax – Juan Jimenez Aug 09 '11 at 15:03
  • I know it should work but it doesn't. Although it doesn't throw an exception, it doesn't delete the row from the database either. – Paul Aug 16 '11 at 13:15
0

The following code works well for me:

var c = db.Set<T>().Find(id);
db.Entry(c).State = EntityState.Deleted;
db.SaveChanges();

If this object wasn't tracked previously by the DbContext then it would hit the database, otherwise it would find it in memory.

Boris Lipschitz
  • 9,236
  • 5
  • 53
  • 63