【问题标题】:Delete a single record from Entity Framework?从实体框架中删除一条记录?
【发布时间】:2013-07-17 09:25:15
【问题描述】:

我在实体框架中有一个名为 employ 的 SQL Server 表,其中有一个名为 ID 的键列。

如何使用 Entity Framework 从表中删除一条记录?

【问题讨论】:

  • db.employ.Remove(db.employ.Find(ID1))
  • @CarterMedlin - 虽然这会起作用,但这是两个数据库命中:一个 SELECT 和一个 DELETE。大多数人认为这非常浪费,特别是因为选择可能比删除花费更多的时间。
  • 由于性能问题,我不建议使用实体框架 Remove 或 RemoveRange。我宁愿只使用以下超级简单的东西: var sql = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD= @your_parameter"; this.your_context.Database.ExecuteSqlCommand(sql, new SqlParameter("@your_parameter", yourParameter));
  • @curiousBoy 我认为当您执行您建议的语句时,EF6 缓存不会反映更改。

标签: c# sql-server entity-framework


【解决方案1】:

不需要先查询对象,你可以通过它的 id 将它附加到上下文中。 像这样:

var employer = new Employ { Id = 1 };
ctx.Employ.Attach(employer);
ctx.Employ.Remove(employer);
ctx.SaveChanges();

或者,您可以将附加条目的状态设置为已删除:

var employer = new Employ { Id = 1 };
ctx.Entry(employer).State = EntityState.Deleted;
ctx.SaveChanges();

【讨论】:

  • 或者,ctx.Entry(employer).State = EntityState.Deleted
  • 这仅在关系被定义为删除级联时才有效。否则上面的代码将因 FK 异常而失败。
  • @mt_serg,我正在向前看 3 步。您最后一次真正不得不从数据库中删除如此简单的记录是什么时候?通常您正在处理包含 FK 关系的更复杂的记录。因此我的评论。
  • @IanWarburton 第二行和第三行(附加和删除)
  • @PaulZahra:有时你有一个来自其他查询或来源的 ID 列表,你需要删除一个。而不是加载对象只是为了删除它们,这样您可以按 ID 删除。你知道,SQL 中的 DELETE 语句通常是这样工作的。
【解决方案2】:

您可以使用SingleOrDefault 来获取与您的条件匹配的单个对象,然后将其传递给您的EF 表的Remove 方法。

var itemToRemove = Context.Employ.SingleOrDefault(x => x.id == 1); //returns a single item.

if (itemToRemove != null) {
    Context.Employ.Remove(itemToRemove);
    Context.SaveChanges();
}

【讨论】:

  • 这不是好办法,因为你是从数据库中选择所有字段!
  • 我就是这样做的。
  • @Ali, Jack - 但我认为这更可取,因为它首先检查您尝试删除的数据是否确实存在,这可以防止任何麻烦。接受的答案本身没有检查。
  • 这是更好的方法。想想看。如果 John Smith 试图删除 id = 1 的项目,Susie Smith 在 30 秒前删除了但 John 不知道怎么办?在这种情况下,您需要访问数据库。
  • @Yusha 为什么?在这两种情况下,结果都是记录消失了。我们真的关心这是现在还是 30 秒前发生的?跟踪某些比赛条件并不是那么有趣。
【解决方案3】:
  var stud = (from s1 in entities.Students
            where s1.ID== student.ID
            select s1).SingleOrDefault();

  //Delete it from memory
  entities.DeleteObject(stud);
  //Save to database
  entities.SaveChanges();

【讨论】:

  • FirstOrDefault 很危险。要么你知道只有一个(所以使用SingleOrDefault),或者有多个,应该循环完成。
【解决方案4】:
Employer employer = context.Employers.First(x => x.EmployerId == 1);

context.Customers.DeleteObject(employer);
context.SaveChanges();

【讨论】:

  • 如果没有 ID 为 1 的对象,这会保护吗?不会抛出异常吗?
  • @JackFairfield 我认为你应该检查空对象。并根据它执行删除。
  • First 很危险。要么你知道只有一个(所以使用Single),或者有多个,应该循环完成。
【解决方案5】:

我正在使用带有 LINQ 的实体框架。以下代码对我很有帮助;

1- 多条记录

 using (var dbContext = new Chat_ServerEntities())
 {
     var allRec= dbContext.myEntities;
     dbContext.myEntities.RemoveRange(allRec);
     dbContext.SaveChanges();
 }

2- 单条记录

 using (var dbContext = new Chat_ServerEntities())
 {
     var singleRec = dbContext.ChatUserConnections.FirstOrDefault( x => x.ID ==1);// object your want to delete
     dbContext.ChatUserConnections.Remove(singleRec);
     dbContext.SaveChanges();
 }

【讨论】:

  • 对于单一记录,为什么不使用SingleOrDefault 而不是FirstOrDefault
  • 无论何时使用 SingleOrDefault,您都清楚地表明查询最多只能产生一个结果。另一方面,当使用 FirstOrDefault 时,查询可以返回任意数量的结果,但您声明您只想要第一个 stackoverflow.com/a/1745716/3131402
  • 是的,如果有多个记录,为什么删除任意记录是正确的?特别是在这种情况下,id 是关键,所以应该有一个:如果有多个,那就是一个错误(Single 会检测到)
  • @MarkSowul 你是对的。我已经编辑了使用 FirstOrDefault 的答案。
  • @BaqerNaqvi RemoveRange 是从性能角度删除实体的糟糕方法。尤其是当您的实体因外键的所有导航属性而沉重时。我宁愿使用 var sql = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD= @your_parameter"; this.your_context.Database.ExecuteSqlCommand(sql, new SqlParameter("@your_parameter", yourParameter));
【解决方案6】:

更通用的方法

public virtual void Delete<T>(int id) where T : BaseEntity, new()
{
    T instance = Activator.CreateInstance<T>();
    instance.Id = id;
    if (dbContext.Entry<T>(entity).State == EntityState.Detached)
    {
        dbContext.Set<T>().Attach(entity);
    }

    dbContext.Set<T>().Remove(entity);
}

【讨论】:

    【解决方案7】:

    使用 Entity Framework 6,您可以使用 Remove。 此外,使用 using 确保您的连接已关闭也是一个很好的策略。

    using (var context = new EmployDbContext())
    {
        Employ emp = context.Employ.Where(x => x.Id == id).Single<Employ>();
        context.Employ.Remove(emp);
        context.SaveChanges();
    }
    

    【讨论】:

      【解决方案8】:

      只是想贡献我反复使用的三种方法。

      方法一:

      var record = ctx.Records.FirstOrDefault();
      ctx.Records.Remove(record);
      ctx.SaveChanges();
      

      方法二:

      var record = ctx.Records.FirstOfDefault();
      ctx.Entry(record).State = EntityState.Deleted;
      ctx.SaveChanges();
      ctx.Entry(record).State = EntityState.Detached;
      

      我更喜欢方法2的原因之一是因为在将EF或EFCore设置为QueryTrackingBehavior.NoTracking的情况下,这样做更安全。

      然后是方法3:

      var record = ctx.Records.FirstOrDefault();
      var entry = ctx.Entry(record);
      record.DeletedOn = DateTimeOffset.Now;
      entry.State = EntityState.Modified;
      ctx.SaveChanges();
      entry.State = EntityState.Detached;
      

      这通过设置记录的DeletedOn 属性来利用软删除方法,并且仍然能够保留记录以供将来使用,无论可能是什么。基本上,将其放入回收站


      另外,关于方法3,而不是将整个记录设置为被修改:

      entry.State = EntityState.Modified;
      

      您也只需将列 DeletedOn 设置为已修改:

      entry.Property(x => x.DeletedOn).IsModified = true;
      

      【讨论】:

        【解决方案9】:
            [HttpPost]
            public JsonResult DeleteCotnact(int id)
            {
                using (MycasedbEntities dbde = new MycasedbEntities())
                {
                    Contact rowcontact = (from c in dbde.Contact
                                             where c.Id == id
                                             select c).FirstOrDefault();
        
                    dbde.Contact.Remove(rowcontact);
                    dbde.SaveChanges();
        
                    return Json(id);
                }
            }
        

        你觉得这个,简单与否,你也可以试试这个:

                var productrow = cnn.Product.Find(id);
                cnn.Product.Remove(productrow);
                cnn.SaveChanges();
        

        【讨论】:

          【解决方案10】:

          使用EntityFramework.Plus 可能是一种选择:

          dbContext.Employ.Where(e => e.Id == 1).Delete();
          

          更多示例可here

          【讨论】:

            【解决方案11】:

            你可以像这样简单地做到这一点

               public ActionResult Delete(int? id)
                {
                    using (var db = new RegistrationEntities())
                    {
                        Models.RegisterTable Obj = new Models.RegisterTable();
                        Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
                        if (personalDetail == null)
                        {
                            return HttpNotFound();
                        }
                        else
                        {
                            Obj.UserID = personalDetail.UserID;
                            Obj.FirstName = personalDetail.FName;
                            Obj.LastName = personalDetail.LName;
                            Obj.City = personalDetail.City;
            
                        }
                        return View(Obj);
                    }
                }
            
            
                [HttpPost, ActionName("Delete")]
            
                public ActionResult DeleteConfirmed(int? id)
                {
                    using (var db = new RegistrationEntities())
                    {
                        Registration.DAL.RegisterDbTable personalDetail = db.RegisterDbTable.Find(id);
                        db.RegisterDbTable.Remove(personalDetail);
                        db.SaveChanges();
                        return RedirectToAction("where u want it to redirect");
                    }
                }
            

            型号

             public class RegisterTable
            {
            
                public int UserID
                { get; set; }
            
            
                public string FirstName
                { get; set; }
            
            
                public string LastName
                { get; set; }
            
            
                public string Password
                { get; set; }
            
            
                public string City
                { get; set; }
            
            } 
            

            你会调用它的视图

             <table class="table">
                <tr>
                    <th>
                        FirstName
                    </th>
                    <th>
                        LastName
                    </th>
            
                    <th>
                        City
                    </th>
                    <th></th>
                </tr>
            
                @foreach (var item in Model)
                {
                    <tr>
                        <td> @item.FirstName </td>
                        <td> @item.LastName </td>
                        <td> @item.City</td>
                        <td>
                            <a href="@Url.Action("Edit", "Registeration", new { id = item.UserID })">Edit</a> |
                            <a href="@Url.Action("Details", "Registeration", new { id = item.UserID })">Details</a> |
                            <a href="@Url.Action("Delete", "Registeration", new { id = item.UserID })">Delete</a>
            
                        </td>
                    </tr>
            
                }
            
            </table>
            

            我希望这对你来说很容易理解

            【讨论】:

              【解决方案12】:

              您可以在网格的 click 或 celldoubleclick 事件中执行类似操作(如果您使用过)

              if(dgEmp.CurrentRow.Index != -1)
               {
                  employ.Id = (Int32)dgEmp.CurrentRow.Cells["Id"].Value;
                  //Some other stuff here
               }
              

              然后在您的删除按钮中执行以下操作:

              using(Context context = new Context())
              {
                   var entry = context.Entry(employ);
                   if(entry.State == EntityState.Detached)
                   {
                      //Attached it since the record is already being tracked
                      context.Employee.Attach(employ);
                   }                             
                   //Use Remove method to remove it virtually from the memory               
                   context.Employee.Remove(employ);
                   //Finally, execute SaveChanges method to finalized the delete command 
                   //to the actual table
                   context.SaveChanges();
              
                   //Some stuff here
              }
              

              或者,您可以使用 LINQ 查询而不是使用 LINQ To Entities 查询:

              var query = (from emp in db.Employee
              where emp.Id == employ.Id
              select emp).Single();
              

              employ.Id 用作已从 DataGridView 的 CellDoubleClick 事件传递的过滤参数。

              【讨论】:

              • 代码背后的想法是将要删除的记录的 id(employ.Id) 连接到模型(Employee Class),然后将其附加到上下文中的实际表,然后执行内存中的 Remove() 方法最后使用 SaveChanges() 方法执行实际保存到数据库。虽然 LINQ 查询也可以正常工作,但我不喜欢查询表只是为了获取记录的 id 的想法。
              【解决方案13】:

              这是一个安全的方法:

              using (var transitron = ctx.Database.BeginTransaction())
              {
                try
                {
                  var employer = new Employ { Id = 1 };
                  ctx.Entry(employer).State = EntityState.Deleted;
                  ctx.SaveChanges();
                  transitron.Commit();
                }
                catch (Exception ex)
                {
                  transitron.Rollback();
                  //capture exception like: entity does not exist, Id property does not exist, etc...
                }
              }
              

              这里你可以把你想要的所有改动都堆起来,这样你就可以在SaveChanges和Commit之前做一系列的删除,所以只有全部成功才会应用。

              【讨论】:

                【解决方案14】:

                最好的方法是检查然后删除

                        if (ctx.Employ.Any(r=>r.Id == entity.Id))
                        {
                            Employ rec = new Employ() { Id = entity.Id };
                            ctx.Entry(rec).State = EntityState.Deleted;
                            ctx.SaveChanges();
                        }
                

                【讨论】:

                  【解决方案15】:

                  对于一个通用的 DAO,这是可行的:

                      public void Delete(T entity)
                      {
                          db.Entry(entity).State = EntityState.Deleted;
                          db.SaveChanges();
                      }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2016-09-10
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-09-20
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多