2

I am using Entity Framework 6 and I have a repository looking like the following with the Add and Update methods removed to make it shorter:

 public class GenericRepository<T> : IRepository<T> where T : class
{
    public GenericRepository(DbContext dbContext)
    {
        if (dbContext == null) 
            throw new ArgumentNullException("An instance of DbContext is required to use this repository", "context");
        DbContext = dbContext;
        DbSet = DbContext.Set<T>();
    }

    protected DbContext DbContext { get; set; }

    protected DbSet<T> DbSet { get; set; }

    public virtual IQueryable<T> Find(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Where<T>(predicate);
    }

    public virtual IQueryable<T> GetAll()
    {
        return DbSet;
    }

    public virtual T GetById(int id)
    {
        //return DbSet.FirstOrDefault(PredicateBuilder.GetByIdPredicate<T>(id));
        return DbSet.Find(id);
    }

    public virtual void Delete(T entity)
    {
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State != EntityState.Deleted)
        {
            dbEntityEntry.State = EntityState.Deleted;
        }
        else
        {
            DbSet.Attach(entity);
            DbSet.Remove(entity);
        }
    }

    public virtual void Delete(int id)
    {
        var entity = GetById(id);
        if (entity == null) return; // not found; assume already deleted.
        Delete(entity);
    }
}

In my controller I call the repository like this:

    public HttpResponseMessage DeleteTest(int id)
    {
        Test test = _uow.Tests.GetById(id);
        if (test == null)
        {
            return Request.CreateResponse(HttpStatusCode.NotFound);
        }
        try
        {
            _uow.Tests.Delete(test);
            _uow.Commit();
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
        }
    }

This works for a single test but how can I delete for example all tests that have an examId column value of 1 being that examId is one of the columns in the Test table.

  • Do you mean `_uow.Tests.Where(t => t.Id == id).Delete()`? – Mahmoud Gamal Dec 28 '13 at 08:26
  • But my repository does not have a .Where :-( –  Dec 28 '13 at 08:29
  • Make `GetById` return a list of `Test` instead of one test. Make it return `return Test.Where(t => t.Id == id)` – Mahmoud Gamal Dec 28 '13 at 08:30
  • 1
    Actually, EF is a repository by itself. Using repository pattern with EF is just like adding another unnecessary layer of abstraction. – Roman Pushkin Dec 28 '13 at 08:59
  • EF6 has introduced the [`DbSet.RemoveRange` method](http://msdn.microsoft.com/en-us/library/system.data.entity.dbset.removerange(v=vs.113).aspx). Similarly, there is an `AddRange` method. – Zairja May 07 '14 at 15:21

3 Answers3

2

You can create another delete method in your generic repository class, see below:

    public virtual void Delete(Expression<Func<T, bool>> predicate)
    {
        IQueryable<T> query = DbSet.Where(predicate).AsQueryable();
        foreach (T obj in query)
        {
            DbSet.Remove(obj);
        }
    }

Then you can use it like below, it will delete all records which Id equalsid.

  _uow.Test.Delete(n => n.Id = id)
Lin
  • 15,078
  • 4
  • 47
  • 49
1

I'm not sure if EF is able to handle multiple delete now given a certain value, but the last time I did this I had to resort to a loop.

public HttpResponseMessage DeleteTest(int id)
{
  var testList = _uow.Tests.GetAll().Where(o => o.Id == id);
  if (testList.Count() == 0)
  {
      return Request.CreateResponse(HttpStatusCode.NotFound);
  }
  try
  {
      foreach (var test in testList)
      {
        _uow.Tests.Delete(test);
      }
      _uow.Commit();
      return Request.CreateResponse(HttpStatusCode.OK);
  }
  catch (Exception ex)
  {
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
  }
}

If the "test" table is a foreign table linked to a primary table on the "ID" column, you may want to consider doing a cascading delete in this case.

Ronald
  • 1,532
  • 4
  • 18
  • 34
0

You can use RemoveRange()

public virtual void Delete(Expression<Func<T,bool>> predicate)
{
   var query = Context.Set<T>().Where(predicate);
   Context.Set<T>().RemoveRange(query);
}
koryakinp
  • 3,989
  • 6
  • 26
  • 56