C# WinForms+EF5实现绑定数据源软删除(标记IsDeleted为true)
实现Entity Framework 5中BindingSource数据的软删除操作
首先咱们得明确软删除的核心:不是从BindingSource或数据库中物理移除实体,而是修改实体的IsDeleted字段为true,然后持久化到数据库,再更新UI的过滤状态。下面我一步步给你拆解实现步骤:
1. 获取选中实体并标记软删除
先从enrollmedsBindingSource里拿到当前选中的实体(记得替换成你实际的实体类型,比如假设实体叫Enrollmed):
// 获取当前选中的记录 var selectedItem = enrollmedsBindingSource.Current as Enrollmed; if (selectedItem == null) { MessageBox.Show("请选择要删除的记录"); return; } // 标记为软删除状态 selectedItem.IsDeleted = true;
2. 保存更改到数据库
用EF上下文把这个修改同步到数据库:
try { using (var context = new YourDbContext()) // 替换成你的DbContext类名 { // 如果实体是脱离上下文的,需要先附加并标记为修改状态 context.Entry(selectedItem).State = EntityState.Modified; context.SaveChanges(); MessageBox.Show("软删除操作完成"); } } catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}"); }
小提示:如果你的实体是从当前上下文加载的(比如窗体初始化时直接查询的),那EF会自动跟踪更改,不需要手动设置
EntityState.Modified。
3. 刷新BindingSource并维持过滤状态
因为你一开始就设置了只显示IsDeleted=false的记录,所以保存后需要刷新数据源,让被标记删除的条目从DataGridView中消失:
// 方式1:重新查询过滤后的数据源(推荐,确保和数据库完全同步) using (var context = new YourDbContext()) { enrollmedsBindingSource.DataSource = context.Enrollmeds.Where(e => !e.IsDeleted).ToList(); } // 方式2:如果不想重新查询,可重置绑定并确保过滤生效 enrollmedsBindingSource.ResetBindings(false); // 若你之前是通过BindingSource.Filter实现的过滤,重新设置一遍确保生效 enrollmedsBindingSource.Filter = "IsDeleted = false";
4. 关键避坑:禁用物理删除
一定要注意:不要调用enrollmedsBindingSource.Remove(selectedItem)或者context.Enrollmeds.Remove(selectedItem),这些操作会直接物理删除实体,完全违背软删除的逻辑。
完整示例代码
把上面的步骤整合到删除按钮的点击事件里:
private void btnSoftDelete_Click(object sender, EventArgs e) { var selectedItem = enrollmedsBindingSource.Current as Enrollmed; if (selectedItem == null) { MessageBox.Show("请选择一条记录进行删除"); return; } // 增加删除确认弹窗,避免误操作 if (MessageBox.Show("确定要标记这条记录为删除吗?", "确认操作", MessageBoxButtons.YesNo) == DialogResult.No) { return; } try { using (var context = new YourDbContext()) { context.Enrollmeds.Attach(selectedItem); selectedItem.IsDeleted = true; context.Entry(selectedItem).Property(x => x.IsDeleted).IsModified = true; context.SaveChanges(); } // 刷新数据源,重新加载过滤后的列表 using (var context = new YourDbContext()) { enrollmedsBindingSource.DataSource = context.Enrollmeds.Where(e => !e.IsDeleted).ToList(); } MessageBox.Show("记录已标记为删除"); } catch (Exception ex) { MessageBox.Show($"操作失败:{ex.Message}"); } }
额外优化建议
可以在DbContext中重写SaveChanges方法,统一拦截物理删除操作,自动转为软删除,这样能避免误操作:
public override int SaveChanges() { foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted)) { if (entry.Entity is ISoftDelete softDeleteEntity) { // 取消物理删除,改为标记软删除 entry.State = EntityState.Modified; softDeleteEntity.IsDeleted = true; // 还可以顺便记录删除时间 // softDeleteEntity.DeletedTime = DateTime.Now; } } return base.SaveChanges(); } // 定义软删除接口,让实体实现它 public interface ISoftDelete { bool IsDeleted { get; set; } } // 你的实体类实现接口 public class Enrollmed : ISoftDelete { // 其他实体属性... public bool IsDeleted { get; set; } }
这样哪怕不小心调用了context.Remove(selectedItem),也会自动转为软删除,安全性更高。
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

