微软.NET RIA服务通过结合ASP.NET和Silverlight平台来简化传统N层应用模式。 应用逻辑写在中间层上,通过查询、更新、定制方法和服务操作来控制对数据的访问。 .NET RIA服务特性自动地在客户层生成对应的代理类,以调用这些操作。 因为中间层和客户层基于相同的CLR(共同语言运行时库),所以开发人员可以写出在两层上运行的代码。
本文通过在单一Visual Studio解决方案中构造一个简单的N层应用来阐明关键概念。
2.1 创建项目
创建.NET RIA服务N层应用以使用File | New Project来创建Silverligh Web应用项目开始[1]:
接此对话框显示New Silverlight Application对话框。 如果.NET RIA服务已经安装,此对话框显示下面突出圈定的检查框:
默认情况下,该检查框是没有选中的。 要使用.NET RIA服务建N层应用,你必须手动选择它。
结果解决方案看起来象这样:
此时,我们已经创建了一个由2个项目组成的单一解决方案:
1. SilverlightApplication1 ——此项目包含Silverlight代码。 我们称它为客户端项目。 这将成为我们的客户层。
2. SilverlightApplication1.Web——此项目包含ASP.NET Web应用代码。 我们称它为服务器项目。 这将成为我们的中间层。
该解决方案和标准Silverlight Web应用之间的主要区别是上面选择的“Enable .NET RIA Services”检查框。 此检查框在客户端和服务器项目间形成了关联,允许共享应用逻辑。 它被非正式的称作“RIA链接”,在“理解Silverlight客户端代码生成”和“理解N层类库”中将更详细地阐述。
2.2 转化现有Web应用
如上所述,对于是否启用“RIA链接”,你可事后改变主意。 这包括修改你已经建成的现有Web应用项目。 为改变该设置,要选择客户端项目并检查其属性(右击 | Properties或用菜单项Project | SilverlightApplication1 Properties…)。 如果.NET RIA服务已经安装,则该屏将显示如下突出圈定的下拉框。
为修改Web和Silverlight应用项目间的“RIA链接”,要从“.NET RIA Services Link”下拉框里的可选项中选择一个Web应用。 为禁用该链接,要选择“<No Server Project Set>”。 在我们的例子中,该屏仅仅确认我们早先通过选定“Enable .NET RIA Services”检查框而做出的选择。
2.3 从中间层呈现数据
此时,我们已经有了一个启用了新的.NET RIA服务功能的普通Silverlight Web应用项目。 为了演示该新功能,我们将首先做一些数据供我们的中间层使用。
2.4 从中间层访问数据
在此例中,我们的中间层将使用从数据库来的数据。 数据库的使用并不是.NET RIA服务框架所要求的。 客户层对中间层使用的数据访问技术或模式一无所知。
为了在我们的中间层使用数据库,我们将用实体框架访问AdventureWorks数据库。 我们先右击服务器项目,选Add New Item菜单项并选择Data类型:
对此应用,我们从AdventureWorks数据库中只选择2张表:
2.5 在中间层上创建DomainService
现在我们到了演示.NET RIA服务框架特性的最重要一步: 在中间层上创建DomainService。 DomainService是一个为特定数据领域呈现实体和操作的类。 开发人员也是这里增加应用逻辑。
.NET RIA服务框架包含有衔接代码在DomainService类中声明实体和操作为其它层所用。
我们选择服务器项目并选择Add New Item来创建示例DomainService。 在Web类型下,有Domain Service Class模板。 我们选择将此新的DomainService类叫作ProductService:
该模板调用一个向导来帮助构建DomainService类。 在此例中,我们现在刚创建的AdventureWorks模型,并仅呈现一个实体:Product。 我们不“Enable editing”,意为Product实体是只读的[2].
在我们提交该对话框后,新的DomainService类就将在所选的项目中创建。 在此例中,我们称它为ProductService。 这里是生成的代码:
注意生成代码的下列特征:
- 该类派生自 LinqToEntitiesDomainService,它是内建在.NET RIA服务框架内的一个抽象类[3].
- 该通用基类与我们早先创建的AdventureWorks_DataEntities类绑定。
- DomainService类标有[EnableClientAccess] ,以指明它对客户层可见。
- 因为我们要求呈现Product实体,所以生成了一个GetProduct()查询方法。
- 在GetProduct中生成了实现代码以从AdventureWorks_DataEntities对象场景获得数据。
该新的DomainService类是我们可以添加自己应用逻辑的地方。 例如,我们可以修改GetProduct()方法中的逻辑以仅仅选择库存Products。 或者,我们可以给该方法增加一个参数来指定产品类型并改变我们的查询来仅仅选择那些产品。 我们还可添加新的带参数方法,以适应对我们的应用有意义的其它选择类型。
这里的重要之处是DomainService类给中间层提供了公共接口。 向导生成的代码仅仅是一个起始点,我们将在此处进入我们的应用逻辑。
第二个重要之处是我们现在可以不做任何修改地运行我们的应用,Product实体可用于中间层和客户层两者之上。 使此成为可能的机制在下面阐述。
2.6 从Silverlight客户端访问数据
还记得我们创建此应用时建立的“RIA链接”吗? 现在它就开始发挥作用了。
如果我们生成此解决方案并在客户端项目中点击“Show All Files”,我们将看到这个:
注意客户端项目现在有一个目录,叫作Generated_Code,包含一个生成的文件。 上面的屏幕截图显示了该文件的几行。
该生成文件包含我们所统称的客户端代理类。 这些类从我们在服务器项目中创建的DomainService类合成而来。
生成这些代理类的机制和它们发挥作用的方式在“理解Silverlight客户端代码生成”一节讲述,但是需要注意的重要方面有:
· 每当服务器上的DomainService类进行了修改,并且客户端项目或解决方案重新生成,那么这些客户端代理类就重新生成。 你不要修改这些代理类,因为它们会被覆盖。
· 对于每个由DomainService类呈现的实体类型(此例中为Product实体),都会生成一个防波堤客户端代理类。
· 每个DomainService呈现的操作都由一个生成的DomainContext类来提供客户端访问。 此例中生成了ProductContext类,它呈现了GetProductQuery()方法,能够用作DomainContextLoad()方法的参数,以调用该中间层上的DomainService(即ProductServce)中的GetProduct()查询方法。 见“如何查询实体。”
2.7 在Silverlight客户端使用数据
对服务器端的标有[EnableClientAccess]定制属性的每个DomainService,客户端项目中生成的文件都包含有一个DomainContext类。 Silverlight客户端可实例化这些DomainContext并与其互动。 下例显示人们如何照此在网格中显示产品。
我们向客户端项目添加一个DataGrid,如下所示:
然后我们向幕后文件添加一些代码来实例化生成的DomainContext,从服务器提取产品,并将其绑定到DataGrid:
我们现在可以运行该应用。所见如下:
2.8 总结
本节对使用.NET RIA服务框架的一个N层Silverlight应用项目的关键概念作了一个简述。 由此得到的要点是:
· 通过在Silverlight项目和Web项目间建立“RIA链接”,可以把标准Silverlight Web应用项目变成N层应用。[4].
· 最简单的N层应用由一个解决方案里两个分别的项目组成; 一个用于ASP.NET服务器项目(中间层),而另一个用于Silverlight客户端项目(客户端)。
· 服务器项目中的DomainService 呈现一组实体和操作,适用于某一特定领域。 应用开发人员将其定制的应用逻辑放置到该DomainService类中。
· 在生成解决方案时,客户端代理类会自动生成到Silverlight客户端项目中[5],与服务器的DomainService呈现的实体和操作相对应。
· Silverlight客户端代码与生成的DomainContext代理类互动,以获得和操纵对应的实体。
· 服务器和客户层都操作一组共同的实体类型,于是能够跨层共享商业逻辑和验证规则。
[1] 你也可使用Add New Project将Silverlight应用加入到一个已有的Web应用项目。
[2]当选定“Enable Editing”时,DomainService类将呈现方法以创建、更新和删除相应的实体。
[3].NET RIA服务框架有针对实体框架和LING to SQL的基类。它还有 一个不区分技术的基类。
[4]在创建项目时使用“Enable .NET RIA Services”检查框
[5]多个Silverlight客户端项目可以同单个ASP.NET Web应用相关联,并且每个都会获得自己的客户端代理类。