Entity Framework中新增数据后如何刷新BindingSource?
我刚接触EF的时候也遇到过一模一样的问题!核心原因其实很简单:你一开始绑定的是context.Employees.ToList()返回的静态List集合,这个集合不会自动同步数据库的新增数据,而ResetBindings()只是通知控件刷新现有数据的显示,不会帮你从数据库重新拉取新记录。
下面给你几个针对性的解决方案,按实现复杂度从低到高排序:
方案1:重新查询数据库并重新绑定(最简单直接)
模态对话框关闭后,直接重新从数据库获取最新的员工列表,赋值给BindingSource的DataSource:
// 模态对话框关闭后的代码(比如DialogResult.OK分支) using(var context = new YourDbContext()) // 如果上下文是局部实例的话 { employeeBindingSource.DataSource = context.Employees.ToList(); } // 如果你的上下文是全局单例的,直接用现有上下文查询即可 // employeeBindingSource.DataSource = context.Employees.ToList(); // 可选:如果GridControl没有自动响应,手动触发刷新 gridControl1.RefreshDataSource();
这个方法的优点是简单粗暴,不需要额外处理集合的变化,适合小型应用或者数据量不大的场景。
方案2:使用ObservableCollection实现自动刷新
如果希望新增数据后不用重新查询,而是直接把新对象加入集合就能让GridControl自动刷新,可以用ObservableCollection<T>(它实现了INotifyCollectionChanged接口,能自动通知BindingSource和控件更新):
步骤1:表单加载时绑定ObservableCollection
// 表单加载事件 var employeeList = new ObservableCollection<Employee>(context.Employees.ToList()); employeeBindingSource.DataSource = employeeList;
步骤2:模态对话框新增数据后,将新对象加入集合
假设模态对话框返回了新增的Employee对象(比如通过属性或方法获取):
var dialog = new AddEmployeeDialog(); if(dialog.ShowDialog() == DialogResult.OK) { var newEmployee = dialog.NewEmployee; // 先保存到数据库(如果对话框里没做的话) context.Employees.Add(newEmployee); context.SaveChanges(); // 将新对象加入绑定的ObservableCollection ((ObservableCollection<Employee>)employeeBindingSource.DataSource).Add(newEmployee); }
这样GridControl会自动感知到集合的变化,立刻显示新记录,不需要调用ResetBindings()或RefreshDataSource()。
方案3:利用EF的ChangeTracker同步新增实体(适用于同一上下文实例)
如果你的主表单和模态对话框共用同一个DbContext实例,新增的实体已经在上下文的ChangeTracker里了,可以直接从ChangeTracker中提取新增的Employee,加入现有集合:
// 模态对话框关闭后 var currentList = (List<Employee>)employeeBindingSource.DataSource; // 从ChangeTracker中筛选出新增的Employee实体 var newEmployees = context.ChangeTracker.Entries<Employee>() .Where(entry => entry.State == EntityState.Added) .Select(entry => entry.Entity) .ToList(); // 加入现有集合 currentList.AddRange(newEmployees); // 通知控件刷新 employeeBindingSource.ResetBindings(false);
注意:这个方法只适用于主表单和对话框使用同一个DbContext实例的情况,如果对话框用了新的上下文,ChangeTracker里不会有新增的实体,就需要用方案1或2。
为什么原来的ResetBindings(false)没用?
再强调一下:你绑定的ToList()返回的是普通List,它没有实现INotifyCollectionChanged接口,当数据库新增数据后,这个List里并没有新记录,ResetBindings()只是告诉控件“现有数据的属性可能变了”,但现有数据本身没有新增,所以控件自然不会显示新内容。
内容的提问来源于stack exchange,提问作者Stephen Pefanis

