EF Core+WinForms:DataGridView新增行无法提交至数据库问题
问题原因及解决办法
为什么List<T>不能新增行
List<T>没有实现IBindingList接口,DataGridView无法识别它支持新增行操作,所以会出现你截图里的错误。改用BindingList<T>是正确的方向,但新增行保存不了是另一个独立问题。
为什么BindingList新增的行保存不了
你创建的BindingList<Product>只是把原List的数据做了包装,但新增的Product对象并没有被EF Core的DbContext追踪。EF只会保存它正在追踪的实体,所以调用SaveChanges()时,这些新对象不会被插入数据库。
解决办法
方法一:用EF的Local集合绑定(推荐)
直接绑定DbContext中实体的Local集合生成的BindingList,这样新增的对象会自动被上下文追踪:
// 先把符合条件的数据加载到上下文的Local集合 context.Products .Where(p => p.Price > 5) .OrderBy(p => p.Name).ThenBy(p => p.Id) .Load(); // 用Load()替代ToList(),数据会存入Local集合 // 绑定Local集合的BindingList,新增对象自动被EF追踪 dataGridView1.DataSource = context.Products.Local.ToBindingList();
之后保存时直接调用context.SaveChanges(),新增和修改的行都会被提交到数据库。
方法二:手动追踪新增对象
如果还是想用原来的List转BindingList的方式,需要监听BindingList的新增事件,把新对象添加到DbContext中:
List<Product> p_list = context.Products .Where(p => p.Price > 5) .OrderBy(p => p.Name).ThenBy(p => p.Id) .ToList(); var p_list_binding = new BindingList<Product>(p_list); // 监听新增事件,让EF追踪新对象 p_list_binding.ListChanged += (sender, e) => { if (e.ListChangedType == ListChangedType.ItemAdded) { var newProduct = p_list_binding[e.NewIndex]; context.Products.Add(newProduct); } }; dataGridView1.DataSource = p_list_binding;
保存时同样调用context.SaveChanges()即可。
注意
不管用哪种方法,保存操作都需要显式调用context.SaveChanges()(或异步的SaveChangesAsync())才能把修改和新增提交到数据库。
内容的提问来源于stack exchange,提问作者Maciej
相关产品推荐
相关产品推荐

