从实体框架中删除一条记录?
Posted
技术标签:
【中文标题】从实体框架中删除一条记录?【英文标题】: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 缓存不会反映更改。 【参考方案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 时,查询可以返回任意数量的结果,但您声明您只想要第一个 ***.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();
【讨论】:
以上是关于从实体框架中删除一条记录?的主要内容,如果未能解决你的问题,请参考以下文章