WCF实例 —— 自定义DataService数据模型(1)

ADO.NET DataService 默认是暴露EDM数据模型(e.g. Entity Framework) 以提供一种基于OData协议的数据服务,但也支持自定义的数据模型,可以选择别的数据源来实现一个DataService。当然作为自定义的数据模型,查询需要返回实现 IQueryable 接口的对象,更新则需要实现 IUpdatable 接口。

先创建一个 WCF Service Application

删掉默认的 Service1.svc 和 IService.cs,添加一个 WcfDataService.svc 项目

查看 SVC 文件的 Markup,你会发现它加上 DataServiceHostFactory:

<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Service="WcfCustomerDataService.WcfDataService1" %>

如果在开发非IIS Host应用的时候,则使用 WebServiceHost 来寄宿服务。详细参考:Hosting the Data Service (ADO.NET Data Services)

1.定义实体:实体里必须使用 DataServiceKeyAttribute 标注Key。否则DataService运行报错。
[DataServiceKeyAttribute("OrderId")]
public class Order
{
    public int OrderId { get; set; }
    public string Customer { get; set; }
    public IList<Item> Items { get; set; }
}

[DataServiceKeyAttribute("Product")]
public class Item
{
    public string Product { get; set; }
    public int Quantity { get; set; }
}
2. 定义数据模型:
(1) 在 DataModel 的静态构造方法中,添加了一些初始数据,在这里你可以任意扩展数据的来源。
(2) 定义了两个属性:Orders 和 Items, 它们返回 IQueryable<T> 的结果。
public class DataModel
{
    #region Populate Service Data
    static IList<Order> _orders;
    static IList<Item> _items;
    static DataModel()
    {
        _orders = new List<Order> {
          new Order(){ OrderId=1, Customer = "Wendy Wu", Items = new List<Item>()},
          new Order(){ OrderId=2, Customer = "John Gu", Items = new List<Item>()},
          new Order(){ OrderId=3, Customer = "Balance Yao", Items = new List<Item>()}
        };

        _items = new List<Item> {
          new Item(){ Product="Chang", Quantity = 4 },
          new Item(){ Product="Aniseed Syrup", Quantity=5 },
          new Item(){ Product="Toy", Quantity=7 },
          new Item(){ Product="Car", Quantity=1 },
          new Item(){ Product="Ball", Quantity=6}
        };

        _orders[0].Items.Add(_items[0]);
        _orders[1].Items.Add(_items[1]);
        _orders[1].Items.Add(_items[2]);
        _orders[2].Items.Add(_items[3]);
        _orders[2].Items.Add(_items[4]);
    }
    #endregion

    public IQueryable<Order> Orders
    {
        get { return _orders.AsQueryable<Order>(); }
    }

    public IQueryable<Item> Items
    {
        get { return _items.AsQueryable<Item>(); }
    }
}
3. 实现Service 
public class WcfDataService1 : DataService<DataModel>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

运行,在浏览器里输入 http://localhost:50480/WcfDataService1.svc/Orders 就能看到结果:返回Atom协议的XML数据。


PS:Data Service 通过客户端Request的Accept 来决定返回格式。
比如我用 Fiddler 来查询,使用Accept: application/json 那么返回的就是Json格式的数据:

当然除了在 DataModel 中实现属性的方式提供数据查询服务以外,还可以在 Service 中实现方法提供服务。
比如在上面的 WcfDataService1 里加入下面的方法:调用时按照OData协议写Query
[WebGet]
[SingleResult]
public Order TopOrder()
{
    return this.CurrentDataSource.Orders
        .OrderByDescending(o => o.Items.Sum(i => i.Quantity)).First();
}
Data Service 对服务操作有一些具体的限制 
  • 此方法只能接受 [in] 参数。如果对参数进行定义,则每个参数的类型必须为基元类型。
  • 此方法必须返回 void、IEnumerable<T>、IQueryable<T>、T 或基元类 (如整数或字符串)。T 必须为一个类,此类表示数据服务将公开的数据模型中的某个实体类型。若要支持查询选项(如排序、分页和筛选),服务操作方法应返回 IQueryable<T>。
  • 必须用 [WebGet] 或 [WebInvoke] 属性为此方法添加标注。[WebGet] 使调用方能够通过使用 GET 请求调用此方法;[WebInvoke] 使调用方能够通过使用 PUT、POST 或 DELETE 请求调用此方法。
  • 可以用 SingleResultAttribute 为服务操作添加批注,指定此方法的返回值是一个实体而不是一个实体集。这一区别确定了生成的响应序列化。例如,当使用 AtomPub 序列化时,单个资源类型实例将表示为一个 entry 元素,而单个实例集将表示为一个 feed 元素。
4. 客户端调用
创建一个Console工程,添加Service Reference 生成客户端代理,调用DataService:
static void Main(string[] args)
{
    var svcUri = new Uri("http://localhost:50480/WcfDataService1.svc");
    //Query
    var ctx = new DataSvc.DataModel(svcUri);
    var order = ctx.Orders.Where(o => o.OrderId == 3).First();
    Console.WriteLine(order.Customer);
    //Query by customer method 'TopOrder'
    var topOrder = ctx.Execute<DataSvc.Order>(new Uri("/TopOrder", UriKind.Relative)).First();
    Console.WriteLine(topOrder.Customer);
    Console.Read();
}

参考:http://msdn.microsoft.com/zh-cn/library/dd723653.aspx

(2011/7/30 更新)

通过 QueryInterceptorAttribute 和 ChangeInterceptorAttribute 可以对请求进行拦截。
参考:http://msdn.microsoft.com/zh-cn/library/dd744837.aspx


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值