ServiceStack 项目实例 010 ServiceStack.Northwind - 2
ServiceStack.Northwind这个项目中提供了三表关联操作和缓存方式操作数据的示例。
主要的服务文件
CustomersService.cs :查询客户列表
OrdersService.cs : 查询一组订单以及和该组订单相关的订单项,其中每个订单包含客户信息和具体商品详情,共涉及到三个表。
CustomerDetailsService.cs 一个客户及其订单,被前一个服务(OrdersService)调用。
CachedServices.cs 使用缓存方式,对上面三个服务进行封装,缓存使用的MemoryCacheClient。
ServiceStack的缓存支持多种形式存储,包括Memory,Redis,MemoryCached,SQLAlchemy等,但是仅用于缓存自身的服务,并不是通用功能的缓存,所以使用范围很有限。
CustomersService.cs的代码,获取所有用户的列表,这个功能很简单,不加说明了。
publicCustomersResponseGet(Customersrequest){varcustomers=Db.Select<Customer>();returnnewCustomersResponse{Customers=customers};}
OrdersService.cs 的代码,用来获取多组订单信息,注意是多组,使用了.net集合处理的一些功能。这个服务先获取一组或一个订单,再根据订单获取订单详情信息,获取订单详情的时候根据订单ID对订单详情数据进行分组。
publicclassOrdersService:ServiceStack.ServiceInterface.Service{//指定分页式每页几条记录privateconstintPageCount=8;publicobjectGet(Ordersrequest){//获取一组或一个订单varorders=request.CustomerId.IsNullOrEmpty()?Db.Select<Order>(order=>order.OrderByDescending(o=>o.OrderDate)).Skip((request.Page.GetValueOrDefault(1)-1)*PageCount).Take(PageCount).ToList():Db.Select<Order>(order=>order.Where(o=>o.CustomerId==request.CustomerId).OrderByDescending(o=>o.CustomerId));if(orders.Count==0)returnnewOrdersResponse();//根据订单获取订单详情信息,并据订单ID对订单详情数据进行分组varorderDetails=Db.Select<OrderDetail>(detail=>Sql.In(detail.OrderId,orders.ConvertAll(x=>x.Id)));varorderDetailsLookup=orderDetails.ToLookup(o=>o.OrderId);varcustomerOrders=orders.ConvertAll(o=>newCustomerOrder{Order=o,OrderDetails=orderDetailsLookup[o.Id].ToList()});returnnewOrdersResponse{Results=customerOrders};}}
分步说明:1 订单列表
获取订单信息,判断传入的CustomerId 是否为空,如果CustomerId为空,执行分页方式查询订单的列表,分页的语法和EF中是相同的;如果有CustomerId,就会执行获取一条订单的操作。
varorders=request.CustomerId.IsNullOrEmpty()?Db.Select<Order>(order=>order.OrderByDescending(o=>o.OrderDate)).Skip((request.Page.GetValueOrDefault(1)-1)*PageCount).Take(PageCount).ToList():Db.Select<Order>(order=>order.Where(o=>o.CustomerId==request.CustomerId).OrderByDescending(o=>o.CustomerId));
根据获取的OrderId的列表,获取订单详情列表。
varorderDetails=Db.Select<OrderDetail>(detail=>Sql.In(detail.OrderId,orders.ConvertAll(x=>x.Id)));
其中
orders.ConvertAll(x=>x.Id)
的内容如下:
这个表达式
detail=>Sql.In(detail.OrderId,orders.ConvertAll(x=>x.Id))
实现的效果和SQL中的In子句对应,不过传入的参数有一点差异,第一个参数detail.OrderId指定字段名,第二个参数需要是一个×××值ID的列表,如上图跟踪时的oid的结构。
分步说明:2 分组的订单详情列表
在这个示例中orderDetails 变量查询后获得了44项数据。下一步根据OrderId对获得的这44项数据进行分组。
varorderDetailsLookup=orderDetails.ToLookup(o=>o.OrderId);
跟踪的结构如下图:
可以看到根据8个OrderId, 将44个订单详情数据分组成8组,并且是可以根据OrderId为索引,获取其中某一组的信息(在下一步我们可以看到这个过程)。
(ToLookup是.net集合中内置的一个函数,对集合中数据根据某一个字段进行分组)
分步说明:3 将订单列表和分组的详情列表组合
现在我们获得了8个订单项,还有44个根据订单的ID分组好的详情列表,下面我们把每一条订单的数据和对应的订单详情组合起来。
通过ConvertAll函数,逐项添加CustomerOrder,每个CustomerOrder包含有一个订单数据,和一组和该项订单相关的订单详情项。
varcustomerOrders=orders.ConvertAll(o=>newCustomerOrder{Order=o,OrderDetails=orderDetailsLookup[o.Id].ToList()});
跟踪的结果如下:
有8个订单项,每个订单包含有数量不等的订单详情项。也就是一个订单记录对应了多个购买的商品。
源代码下载:http://down.51cto.com/data/1976805
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。