域服务

域服务是封装 WCF RIA Services 应用程序业务逻辑的 Windows Communication Foundation (WCF) 服务。域服务以服务层形式公开一组相关操作。定义域服务时,请指定通过域服务允许的数据操作。

设计域服务时,应将域服务视为希望用户在应用程序中执行的一组相关任务。通常,此类任务会涉及少量密切相关的实体。例如,在费用报告应用程序中,您可以公开费用报告、行项目和详细信息所对应的实体,然后将帐户和付款的实体放在单独的域服务中。

域服务及其数据源

DomainService 类是用作域服务的所有类的基类。若要创建绑定到自定义数据对象的域服务,请创建一个直接派生自 DomainService 的类。但如果您的域服务绑定了 ADO.NET 实体模型或公开了指向 SQL 数据库的 LINK,则还存在派生自您改用的 DomainService 的特殊抽象类。

  • 若要创建绑定到 ADO.NET 实体模型的域服务,请创建一个派生自 LinqToEntitiesDomainService 的类。RIA Services 提供了 LinqToEntitiesDomainService 类。

  • 若要在应用程序中创建公开 LINQ to SQL 类的域服务,请创建一个派生自 LinqToSqlDomainService 的类。RIA Services 工具包中提供了此类。若要使用此类在应用程序中创建公开 LINQ to SQL 类的域服务,则必须下载 RIA Services 工具包。

在使用**“添加新的域服务类”**对话框创建域服务时,创建的域服务的类型将基于公开的实体。

域服务类必须用 EnableClientAccessAttribute 特性进行标记才能使服务可用于客户端项目。在**“添加新的域服务类”对话框中选中“启用客户端访问”**复选框时,EnableClientAccessAttribute 特性自动应用于域服务。当 EnableClientAccessAttribute 特性应用于域服务时,RIA Services 将为客户端项目生成对应的类。例如,在将 EnableClientAccessAttribute 特性应用于名为 HRService 的域服务(它公开了名为 Employee 的实体)时,RIA Services 将在客户端项目中生成名为 HRContext 的域上下文,并生成客户端版本的 Employee 实体。

WCF 和域服务

作为一项 Windows Communication Foundation (WCF) 服务,域服务是基于 WCF 概念构建的。域服务保留了以下内容:

  • WCF 服务的标准用法

  • 现有 WCF 编程模型构造,如操作协定、操作行为和服务行为

  • 标准 WCF 自定义功能,如绑定配置、行为配置和管理基础结构

域上下文通过使用 WCF ChannelFactory 与 RIA Services 域服务进行通信,以便创建一个通道,并向该通道传递一个已从域服务生成的服务协定。

默认情况下,仅为域服务启用二进制终结点。不需要其他配置即可使用二进制终结点。若要使用其他终结点(如 OData、JSON、SOAP 或自定义主机),您必须在 Web.config 文件中注册终结点工厂,如下所示:

<configSections>
  <sectionGroup name="system.serviceModel">
    <section name="domainServices" type="System.ServiceModel.DomainServices.Hosting.DomainServicesSection, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" allowDefinition="MachineToApplication" requirePermission="false" />
  </sectionGroup>
</configSections>

<system.serviceModel>
  <domainServices>
    <endpoints>
      <add name="json" type="Microsoft.ServiceModel.DomainService.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainService.Hosting" />
    </endpoints>
  </domainServices>
<system.serviceModel>

System.ServiceModel.DomainServices.Hosting 命名空间包含 RIA Services 中支持的终结点。Microsoft.ServiceModel.DomainServices.Hosting 命名空间包含 RIA Services 工具包支持的终结点,如前面的示例中所示的 JsonEndpointFactory。若要创建自定义终结点,您必须创建一个派生自 DomainServiceEndpointFactory 类的类,并重写 CreateEndpoints 方法。

数据操作

您将用于执行要公开的数据操作的方法添加到域服务。例如,可以添加执行以下操作的方法:

  • Query

  • Update

  • Insert

  • Delete

还可以添加更复杂的操作,例如:

  • Invoke:用于实现在没有跟踪或延迟执行的情况下需执行的操作。此方法仅用于非实体数据,且只能在不能改用查询、更新、插入或删除操作时使用。

  • Named Update:用于实现不属于简单修改操作的自定义操作。

在公开域服务时,将在域上下文中生成 EntitySet 对象,该域上下文具有指示允许从客户端执行的操作(插入、更新或删除)的属性。可以通过修改实体集合,然后调用 SubmitChanges 方法来执行数据修改。

在绝大多数方案中,您都应使用查询操作,而不是调用操作来加载数据。查询方法会返回单个 Entity 对象、一个 IQueryable<Entity> 对象或一个 IEnumerable<Entity> 对象。查询方法是由中间层上的 DomainService 以及客户端上的 DomainContext 支持的数据模式的必要组成部分。RIA Services 框架会在客户端项目中仅为那些从 DomainService 中的查询方法返回的实体生成实体。

调用操作提供一种带外机制,用于返回非实体数据和执行具有副作用的操作。有关副作用的更多信息,请参见 HasSideEffects 属性。调用操作通常不适用于查询方法。即使调用操作返回了实体,也只在该实体由查询方法返回时,才会为客户端项目生成该实体。

约定

在添加用于执行这些操作的方法时,这些方法必须与操作的预期签名匹配。除了与签名匹配外,方法还必须包含与该数据操作的命名约定匹配的名称前缀。如果方法的名称不是以预期前缀开头,则必须对该操作应用相应的特性。如果该操作的名称与命名约定匹配,则该特性为可选特性。使用命名约定可为开发人员提供更一致的体验。

您无法重载作为域操作的方法。您必须为可从客户端项目调用的每个方法指定一个唯一名称。所有表示域服务操作的方法都必须是公共方法。这些方法必须使用参数的可序列化类型和返回类型。

可以通过向一个方法添加 IgnoreAttribute 特性来阻止公开此方法。

下表提供了数据操作签名。

查询

查询方法必须返回一个实体实例,或返回一个 IEnumerableIQueryable(其中 T 为有效实体类型)。由于不允许重载方法,因此必须为每个采用不同的输入参数(例如 GetEmployees()GetEmployeesByLastName(string lastname))的方法提供一个唯一名称。

下表列出了查询操作的预期签名值。

返回值

IEnumerable<T>IQueryable<T> 或实体

参数

任意数量的参数

名称前缀

任何名称

特性

[Query] (C#)

- 或 -

<Query()> (Visual Basic)

有关更多信息,请参见 QueryAttribute

示例

public IQueryable<Product> GetProducts() (C#)

- 或 -

Public Function GetProducts() As IQueryable(Of Product) (Visual Basic)

更新

下表列出了更新操作的预期签名值。

返回值

参数

实体

名称前缀

更新、更改或修改

特性

[Update] (C#)

- 或 -

<Update()> (Visual Basic)

有关更多信息,请参见 UpdateAttribute

示例

public void UpdateProduct(Product product) (C#)

- 或 -

Public Sub UpdateProduct(ByVal product As Product) (Visual Basic)

插入

下表列出了插入操作的预期签名值。

返回值

参数

实体

名称前缀

插入、添加或创建

特性

[Insert] (C#)

- 或 -

<Insert()> (Visual Basic)

有关更多信息,请参见 InsertAttribute

示例

public void InsertProduct(Product product) (C#)

- 或 -

Public Sub InsertProduct(ByVal product As Product) (Visual Basic)

删除

下表列出了删除操作的预期签名值。

返回值

参数

实体

名称前缀

删除或移除

特性

[Delete] (C#)

- 或 -

<Delete()> (Visual Basic)

有关更多信息,请参见 DeleteAttribute

示例

public void DeleteProduct(Product product) (C#)

- 或 -

Public Sub DeleteProduct(ByVal product As Product) (Visual Basic)

调用

调用操作提供一种带外机制,用于返回非实体数据和执行具有副作用的操作。有关副作用的更多信息,请参见 HasSideEffects 属性。调用操作通常不适用于查询方法。

下表列出了调用操作的预期签名值。

返回值

任意

参数

任意数量的参数

名称前缀

任意

特性

[Invoke] (C#)

- 或 -

<Invoke> (Visual Basic)

有关更多信息,请参见 InvokeAttribute

示例

[Invoke]

public decimal GetCompetitorsPrice(Product product) (C#)

- 或 -

<Invoke> _

Public GetCompetitorsPrice(ByVal product As Product) As Decimal (Visual Basic)

命名更新

下表列出了命名更新操作的预期签名值。

返回值

参数

实体

任意数量的其他参数

名称前缀

任何不是以 Insert、Update 或 Delete 前缀作为开头的名称

特性

[Update(UsingCustomMethod=true] (C#)

- 或 -

<Update(UsingCustomMethod:=True)> (Visual Basic)

有关更多信息,请参见 UpdateAttribute

示例

[Update(UsingCustomMethod=true]

public void DiscountProduct(Product product, int percentage) (C#)

- 或 -

<Update(UsingCustomMethod:=True)> _

Public Sub DiscountProduct(ByVal product As Product, ByVal percentage As Integer) (Visual Basic)

向域服务添加应用程序逻辑

定义公开的数据操作后,可以将所需应用程序逻辑添加到域服务类。由向导生成的代码旨在帮助您开始编写应用程序逻辑。您可以直接将逻辑添加到操作方法中,或将逻辑添加到从操作方法调用的方法中。可以将参数添加到现有方法、自定义方法的实现或添加新方法,以提供应用程序所需的功能。有关实现业务逻辑的更多信息,请参见如何:向域服务添加业务逻辑

在实现域服务时,您必须仔细考虑通过服务公开数据的安全风险。有关安全性的更多信息,请参见 WCF RIA Services 的安全性

另请参见

概念

DomainContext 和操作
WCF RIA Services 的安全性