WCF实例 —— 自定义DataService数据模型(2)
在前一篇DataService数据模型(1) 里介绍了如何实现一个内存数据集合的 DataService,接下来研究一下如何实现更新操作。
这里偷了个懒,直接让 DataModel 实现IDataServiceUpdateProvider接口,而 IDataServiceUpdateProvider 实际继承于 IUpdatable 接口。为了实现数据的增加,修改,删除,主要实现下面几个方法:
//增加 object CreateResource(string containerName, string fullTypeName); //修改 void SetValue(object targetResource, string propertyName, object propertyValue); //删除 void DeleteResource(object targetResource); //保存 void SaveChanges(); //回滚 void ClearChanges();PS:实体关联关系的一系列操作,比较复杂,之后讨论。
客户端调用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Services.Client; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var svcUri = new Uri("http://localhost:50480/WcfDataService1.svc"); var ctx = new DataSvc.DataModel(svcUri); Console.WriteLine("[Orders]"); ctx.Orders.ToList().ForEach(o => Console.WriteLine("\t{0}", o.Customer)); Console.WriteLine("---------------"); Console.WriteLine(); var order = ctx.Orders.Where(o => o.OrderId == 2).First(); Console.WriteLine("1.查询OrderId=2的Order.Customer:"); Console.WriteLine("\t{0}", order.Customer); // 括号里的"2"是对应Order主键而不是Index var items = ctx.Execute<DataSvc.Item>(new Uri("/Orders(2)/Items", UriKind.Relative)).ToList(); Console.WriteLine("2.查询OrderId=2的Order.Items:"); items.ForEach(it => Console.WriteLine("\t{0}", it.Product)); Console.WriteLine("3.增加Order:"); Console.WriteLine("\t保存前的Count:" + ctx.Orders.Count()); var addOrder1 = new DataSvc.Order { Customer = "Customer" + Guid.NewGuid().ToString("N") }; ctx.AddToOrders(addOrder1); var addOrder2 = new DataSvc.Order { Customer = "Customer" + Guid.NewGuid().ToString("N") }; ctx.AddToOrders(addOrder2); ctx.SaveChanges(); Console.WriteLine("\t保存后的Count:" + ctx.Orders.Count()); Console.WriteLine("4.修改OrderId=2的Order.Customer:"); Console.WriteLine("\t保存前的Customer:" + order.Customer); order.Customer = "Clark Li"; ctx.SaveChanges(); var query = ctx.Orders.Where(o => o.OrderId == 2).First(); Console.WriteLine("\t保存后的Customer:" + query.Customer); Console.WriteLine("5.删除Order:"); Console.WriteLine("\t保存前的Count:" + ctx.Orders.Count()); var delOrder1 = ctx.Orders.Where(o => o.OrderId == addOrder1.OrderId).First(); ctx.DeleteObject(delOrder1); ctx.SaveChanges(); Console.WriteLine("\t保存后的Count:" + ctx.Orders.Count()); Console.WriteLine(); Console.WriteLine("[Orders]"); ctx.Orders.ToList().ForEach(o => Console.WriteLine("\t{0}", o.Customer)); Console.WriteLine("---------------"); Console.Read(); } } }
运行结果:

这里偷了个懒,直接让 DataModel 实现IDataServiceUpdateProvider接口,而 IDataServiceUpdateProvider 实际继承于 IUpdatable 接口。为了实现数据的增加,修改,删除,主要实现下面几个方法:
//增加 object CreateResource(string containerName, string fullTypeName); //修改 void SetValue(object targetResource, string propertyName, object propertyValue); //删除 void DeleteResource(object targetResource); //保存 void SaveChanges(); //回滚 void ClearChanges();PS:实体关联关系的一系列操作,比较复杂,之后讨论。
另外需要提到的是 IDataServiceUpdateProvider接口设计中支持批量特性,这就允许在一个事务中一次更新很多的资源。换句话说可以在SaveChangeds()方法调用前,调用IDataServiceUpdateProvider.SetValue() 或者 CreateResource()多次。这似乎看起来比较简单,但是对接口的实现却影响很大。在某个方法实现上,不可以立即将请求反映到数据源上,而是记录所发生的事情并在最后一次性的提交所有操作。
如果数据存放在数据库中,那么数据库系统会自动的在事务中记录所有的命令操作(比如:Entity Framewok)。但在这个例子中使用了内存对象存放数据,所以需要记录在SaveChanges()前所发生的一切。
因此在 DataModel 中,增加了 List<Action> _actions 来记录 SaveChanges() 之前的操作(请求)。
然后在 CreateResource, SetValue, DeleteResource 时都只是将操作暂存在 _actions 里。
SaveChanges 时 ForEach 所有暂存的 Action,一口气调用。 ClearChanges 则简单的把 _actions 清空。
客户端调用:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Services.Client; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var svcUri = new Uri("http://localhost:50480/WcfDataService1.svc"); var ctx = new DataSvc.DataModel(svcUri); Console.WriteLine("[Orders]"); ctx.Orders.ToList().ForEach(o => Console.WriteLine("\t{0}", o.Customer)); Console.WriteLine("---------------"); Console.WriteLine(); var order = ctx.Orders.Where(o => o.OrderId == 2).First(); Console.WriteLine("1.查询OrderId=2的Order.Customer:"); Console.WriteLine("\t{0}", order.Customer); // 括号里的"2"是对应Order主键而不是Index var items = ctx.Execute<DataSvc.Item>(new Uri("/Orders(2)/Items", UriKind.Relative)).ToList(); Console.WriteLine("2.查询OrderId=2的Order.Items:"); items.ForEach(it => Console.WriteLine("\t{0}", it.Product)); Console.WriteLine("3.增加Order:"); Console.WriteLine("\t保存前的Count:" + ctx.Orders.Count()); var addOrder1 = new DataSvc.Order { Customer = "Customer" + Guid.NewGuid().ToString("N") }; ctx.AddToOrders(addOrder1); var addOrder2 = new DataSvc.Order { Customer = "Customer" + Guid.NewGuid().ToString("N") }; ctx.AddToOrders(addOrder2); ctx.SaveChanges(); Console.WriteLine("\t保存后的Count:" + ctx.Orders.Count()); Console.WriteLine("4.修改OrderId=2的Order.Customer:"); Console.WriteLine("\t保存前的Customer:" + order.Customer); order.Customer = "Clark Li"; ctx.SaveChanges(); var query = ctx.Orders.Where(o => o.OrderId == 2).First(); Console.WriteLine("\t保存后的Customer:" + query.Customer); Console.WriteLine("5.删除Order:"); Console.WriteLine("\t保存前的Count:" + ctx.Orders.Count()); var delOrder1 = ctx.Orders.Where(o => o.OrderId == addOrder1.OrderId).First(); ctx.DeleteObject(delOrder1); ctx.SaveChanges(); Console.WriteLine("\t保存后的Count:" + ctx.Orders.Count()); Console.WriteLine(); Console.WriteLine("[Orders]"); ctx.Orders.ToList().ForEach(o => Console.WriteLine("\t{0}", o.Customer)); Console.WriteLine("---------------"); Console.Read(); } } }
运行结果: