现在的位置: 首页 > 综合 > 正文

.NET 4.0 – Winform Control – DataGridView 数据绑定(ADO.NET Entity Framework)

2013年08月20日 ⁄ 综合 ⁄ 共 5830字 ⁄ 字号 评论关闭

 之前写过一篇文章关于 DataGridView 如何利用 BindingSource 绑定1:N的多表数据(.NET 2.0 - WinForm Control - DataGridView 数据绑定) 。这里翻出来重写下,将绑定的数据源由 DataSet 换成现在流行的 Entity Framework~

 

示例代码下载:http://download.csdn.net/source/3273686

使用的是ms sql express数据库,数据库文件的路径需要自行修改。

1.数据的准备:
数据库使用的 Northwind 里的3个表: customers, orders, order details
由数据库导出 Entities Model 的过程这里不说了,直接看看导出的EF:

相比之前的版本 DataSet 通过 Relations 属性来保持上面3个表的关系。
DataSet 添加 Relation 的示例代码:

而在EF中,DB中如果已经设置了外键关联,那么EF就能够自动生成实体的关系,就是 Navigation Properties

通过代码: var order = northwind.Orders.First().Order_Details 可以返回对应 order 的 order_details

2. 数据准备完毕,现在来看看绑定部分的代码:

因为EF已经帮你做完ORM了(不用你写sql,不用你Adapter.Fill),你直接用就可以了。因为 linq2Entities 的延迟加载特性,每次customer变化的时候,其order,order_deails都是即时查询而不是一开始就读入再过滤,所以我们保持一份 ObjectContext 的实例。如果 ObjectContext 在一次绑定之后就销毁,将导致绑定连动失效。在Form_Load时实例化,Form_Closing时销毁:

3.  数据绑定:
1) customerBindingSource直接绑定northwind.Customers
2) orderBindingSource绑定customerBindingSource,并设置DataMember为Customers的Navigation Property——"Orders"
3) orderDetailBindingSource则绑定orderBindingSource,并设置DataMember为Orders的Navigation Property——"Order_Details"
 

4.数据的Navigate,直接调用BindingSource的MoveXXX()方法就可以了。

到此为止,用BindingSource绑定EF就完成了。运行下看看绑定连动的效果:

接下来,实现一下更新DB的代码,不过已经和BindingSource没什么关系了。
因为默认的绑定是双向绑定,也就是画面上任何的修改,都会影响到EF的缓存,可以通过ObjectStateManager获得所有修改过的Entity(返回的是 IEnumerable<ObjectStateEntry>):
var updated = northwind.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
ObjectStateEntry里保存着修改过的Entity, 还有所有修改过的属性名,修改前的值,修改后的值,因此你可以利用下面的方法打出log:

弹出Alert信息:

看看效果:提示中有所有修改的Entity的Key,以及修改的属性,修改前和修改后的值。

如果用户点击OK,那么直接调用:northwind.SaveChanges(); 就可以了。
如果用户点击Cancel,还要放弃修改过的数据怎么办?我们可以利用 ObjectContext.Refresh 方法,Refresh 第一参数是一个枚举:
1) RefreshMode.StoreWins 表示放弃本地数据,接受DB的数据。
2) RefreshMode.ClientWins 表示继续保持当前的数据,直到调用SaveChanges() 以当前数据更新到DB。
PS: Refresh主要运用场景是处理并发错误,比如你修改的一条数据,正好也被别的客户端修改了,当调用SaveChanges()的时候会抛出:OptimisticConcurrencyException,在该异常里通过 Refresh 来进一步处理数据。(是放弃还是坚持更新)
扯的有点远了,关于 EF 的并发错误处理,详细可以看 MSDN:http://msdn.microsoft.com/zh-cn/library/bb399228.aspx

调用EF更新的代码:

Refresh 里只用了 northwind.Customers 是因为3个表已经有关联关系,所以只从最上面的表刷新就可以了。

引申:使用 ObjectStateManager.GetObjectStateEntities 还可以简化的画面变化检查处理,不再需要一个个TextBox检查是否发生变化了,一句话搞定。

抱歉!评论已关闭.