【问题标题】:How can I use Entity Framework 6 and my repository to delete multiple records?如何使用 Entity Framework 6 和我的存储库来删除多条记录?
【发布时间】:2013-12-28 08:19:43
【问题描述】:

我正在使用 Entity Framework 6,并且我有一个如下所示的存储库,其中删除了 Add 和 Update 方法以使其更短:

 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);
    }
}

在我的控制器中,我这样调用存储库:

    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);
        }
    }

这适用于单个测试,但我如何删除例如所有examId 列值为1 的测试 该examId 是Test 表中的列之一。

【问题讨论】:

  • 你的意思是_uow.Tests.Where(t =&gt; t.Id == id).Delete()
  • 但是我的存储库没有 .Where :-(
  • 使GetById 返回Test 的列表,而不是一个测试。让它返回return Test.Where(t =&gt; t.Id == id)
  • 其实EF本身就是一个仓库。将存储库模式与 EF 一起使用就像添加另一个不必要的抽象层。
  • EF6 引入了DbSet.RemoveRange method。同样,还有一个AddRange 方法。

标签: asp.net-mvc entity-framework entity-framework-6


【解决方案1】:

您可以在通用存储库类中创建另一个删除方法,见下文:

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

然后你可以像下面这样使用它,它会删除所有Id等于id的记录。

  _uow.Test.Delete(n => n.Id = id)

【讨论】:

    【解决方案2】:

    我不确定 EF 现在是否能够在给定特定值的情况下处理多次删除,但我上次这样做时不得不求助于循环。

    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);
      }
    }
    

    如果“测试”表是链接到“ID”列上的主表的外部表,您可能需要考虑在这种情况下进行级联删除。

    【讨论】:

      【解决方案3】:

      你可以使用 RemoveRange()

      public virtual void Delete(Expression<Func<T,bool>> predicate)
      {
         var query = Context.Set<T>().Where(predicate);
         Context.Set<T>().RemoveRange(query);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-27
        • 1970-01-01
        • 2014-11-11
        • 2021-12-23
        • 1970-01-01
        • 1970-01-01
        • 2021-02-11
        相关资源
        最近更新 更多