|
变化管理 ADO.NET Data Service客户端库不支持对象的自动变更监视,这意味着当对象,集合和关系发生变化时,需要开发人员告诉DataServiceContext这些变化,通知DataServiceContext对象的API相当简单,如例4所示: 例4 DataServiceContext变更API 方法 这意味着你要监视对象的变化,并在你自己的代码中通知DataServiceContext对象,表面上看起来这样让人很失望,因为没有实现自动化的变化管理,但这样可以让库变得更有效也更mini。 你可能会对如何监视对象的变化感到奇怪,答案就是生成的代码中,在每个生成的data contract类中,当类中的数据变化时partial方法被调用,如果这些方法从来没有使用过,它们本身不会造成任何资源消耗,你可以在任何支持变化通知的data contracts上使用partial方法机制,只需要在partial方法中调用DataServiceContract即可,不用连接DataServiceContract整个类。 幸运的是,Silverlight已经有一个接口支持变化通知了(INotifyPropertyChange),通过这个接口可以在你的实现中将任何变化通知给感兴趣的人,例如你可以在你的data contract类(在我们的例子中是Product类)中调用InotifyPropertyChange定义一个事件,当数据发生变化时可以激活它,下面就是具体的示例: public partial class Product : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; } 这样当任何属性发生变化时都可以触发一个事件,你可以通过partial方法决定什么时候触发这个事件,例如,当ProductName发生变化时要通知预定人,只需要调用OnProductNameChanged方法,然后触发PropertyChanged事件,传递ProductName通知变化的属性给事件预定人,下面是代码: partial void OnProductNameChanged() 通过在这些可写的属性上调用这些partial方法,监视你对象的变化就很简单了,当对象发生变化时,你可以注册PropertyChanged事件然后通知DataServiceContext对象: //在OnLoadComplete方法中,获取结果然后将它们添加到集合中 products = productQuery.EndExecute(result).ToList();
最后你可以调用product_PropertyChanged方法通知DataServiceContext对象:
void product_PropertyChanged(object sender, PropertyChangedEventArgs e) { Product product = (Product)sender; TheContext.UpdateObject(product); } 同样,在创建对象或删除对象时也需要通知DataServiceContext,如: void addNewButton_Click(object sender, RoutedEventArgs e) { Product theProduct = new Product(); // ... TheContext.AddObject(theProduct); }
void deleteButton_Click(object sender, RoutedEventArgs e) { Product theProduct = (Product)theList.SelectItem; TheContext.DeleteObject(theProduct); theCollection.Remove(theProduct); } 在这些代码中,你可以在你的Silverlight UI中修改这些对象,让数据绑定和变化通知代码确保让DataServiceContext知道所有变化都会引发什么后果,但你如何对这些服务执行真实的更新呢? 通过服务更新 现在你的DataServiceContext对象已经知道数据的变化,但还需要一个方法通知给服务器,为了解决这个问题,DataServiceContext类提供了一个BeginSaveChanges方法,它和本文前面描述的查询都使用了相同的异步方法,BeginSaveChanges方法将所有变化都吸收进DataServiceContext,并将它们发送给服务器: TheContext.BeginSaveChanges(SaveChangesOptions.None, new AsyncCallback(OnSaveAllComplete), null); 调用BeginSaveChanges时,有一个标志枚举调用SaveChangesOptions,这个枚举允许你指定两个选项:是否使用批处理,是否继续,即使某些变化保存失败。通常,我建议使用批处理,实际上,在某些父/子关系类型上批处理是必须的,因为父子之间可能使用了引用完整性约束,这样更新才能保证父子之间的一致性。 保存完毕时,将会执行callback,有两个机制可以传播错误消息给你,首先,如果在执行保存时出现了异常,当你在调用EndSaveChanges时,会抛出异常,因为如此,你可能想要使用try/catch来捕获灾难性的错误;另外,EndSaveChanges返回的类型是一个DataServiceResponse对象,DataServiceResponse有一个HasErrors属性,但在Silverlight 2 Beta 2版本库中它还不够安全: void OnSaveAllComplete(IAsyncResult result) { bool succeeded = true; try { DataServiceResponse response = (DataServiceResponse)TheContext.EndSaveChanges(result);
foreach (OperationResponse opResponse in response) { if (opResponse.HasErrors) { succeeded = false; } }
} catch (Exception ex) { succeeded = false; }
// Alert the User } 你可以重复使用OperationResponse对象来查看是否出现了错误,DataServiceResponse是OperationResponse对象的一个集合,在以后的版本中,你应该可以依赖于DataServiceResponse类自身的HasErrors属性了。 服务调式 在调试服务时,你要执行三个重要的任务:查看DataServiceContext对象中数据的状态,查看ADO.NET Data Services产生的请求,以及捕获服务器错误。 首先我们处理DataServiceContext对象中的实体状态,DataServiceContext类暴露了两个有用的集合:Entities和Links,这些集合是只读的,由DataServiceContext进行跟踪,在调式时,不管你是将对象标记为已变化还是未变化,在调试器中查看这些集合是非常有用的,可以帮助你确定跟踪思路是不是正确的。 注意对你而言,查看你的Silverlight 2程序对服务器的真实请求也是很重要的,最好的方法是使用网络代理,我个人使用的是Fiddler2,如果你对Fiddler2不熟悉,也可以使用Web traffic之类的工具来捕获数据包,查看真正发生了什么。 最后,.NET Framework 3.5 SP1不会将服务端错误传递给客户端了,实际上,服务器上的大部分错误都是服务器吞下去的,调试服务端错误的最好办法是在调试菜单(Debug->Exceptions…)中使用Exception选项,配置调试器停止一切.NET异常,如果你选择了这个选项,你可以通过服务看到抛出的异常。 我在本文的目标是展示ADO.NET Data Service是如何在Silverlight 2和基于服务的模块之间建立起连接的,现在你应该已经知道如何使用ADO.NET Data Service从服务器读取数据和往服务器写数据了,再也不用自己动手设计Web Service了,正如你所看到的,Silverlight、ADO.NET Data Service和LINQ三者的组合让你可以创建强大的基于数据驱动的Web应用程序,具有Web 2.0技术的所有有点。 |





骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价