技术开发 频道

NBearV3 Step by Step教程——IoC进阶

IT168 技术文档】

    简介

    本教程在《NBearV3 Step by Step教程——IoC篇》的基础上,演示如何基于NBearV3的IoC模块开发一个分布式Web应用程序的过程。您将看到,基于NBear的IoC组件,开发分布式系统就和开发单服务器系统一样容易。本教程同时将引导您注意分布式开发和非分布式开发,在实体定义中的注意事项。

    注1:NBearV3提供的分布式支持,从用户视角来说,只要按照《NBearV3 Step by Step教程——IoC篇》的方式,以定义本地服务接口和实现相同的方法定义和实现服务接口,再进行一定的配置和部署,就能在不修改代码,甚至不需重新编译的情况下,使应用程序轻松具有分布式能力,并可以以Service为单位进行多服务器分布部署,且能够由ServiceMQ Server控制,自动实现负载均衡。在NBear封装的逻辑内部,是以ServiceMQ Server为消息中心,基于.Net Remoting进行消息传递,并使用Castle作为IoC容器实现的。

    注2:在阅读本文之前,建议读者先阅读《NBearV3 Step by Step教程——IoC篇》以掌握NBearV3中有关ORM和IoC的基本知识。

    目标

    通过本教程,读者应能够全面掌握使用NBearV3的IoC模块开发单服务器/分布式应用程序的全过程。

    代码

    本教程演示创建的所有工程和代码,包含于可以从sf.net下载的NBearV3最新源码zip包中的tutorials\IoC_Adv_Tutorial目录中。因此,在使用本教程的过程中如有任何疑问,可以直接参考这些代码。

    Step 1 下载NBearV3最新版本及准备

    1.1访问http://sf.net/projects/nbear,下载NBearV3的最新版本到本地目录。

    1.2 将下载的zip文件解压至C:\,您将看到,加压后的NBearV3目录中包括:dist、doc、cases、src、tutorials等目录。其中,在本教程中将会使用的是dist目录中的所有release编译版本的dll和exe和tutorials目录中之前的IoC基础教程。

    1.3 将tutorials目录中的整个IoC_Tutorial目录复制到任意其它位置,并命名为IoC_Adv_Tutorial,我们将以IoC_Tutorial为基础,演示NBearV3中基于IoC的分布式开发的知识。

    Step 2 扩展设计实体及元数据

    2.1 将IoC_Adv_Tutorial中的IoC_Tutorial.sln重命名为IoC_Adv_Tutorial.sln,并在VS2005开发环境中打开。

    2.2在本教程中,对于从IoC_Tutorial继承过来的这些工程,我们会做很小的一些修改,您将注意到,我们做这些修改的原因,并不意味着,一个非分布式系统必须做经过修改才能以分布方式部署。而是,我们将引导您注意,在基于NBear的分布式系统中,实体定义和Service接口设计的重要注意事项。

    2.3 首先,需要注意一个在分布系统中的实体设计规范:两个实体或者多个实体间,要避免双向/循环可读写、可序列化的引用。

    具体举例来说,如果您打开EntityDesigns中的EntityDesigns.cs文件,您将注意到,Category和Product,互相包含了可读写的引用。这会有什么问题呢?在非分布式系统中,只要两个引用不同时是LazyLoad=false,这就完全没问题,您在IoC Tutorial中已经看到了,程序运行得很正常。但是,在分布式情况下,因为,Service的中的方法的参数和返回值,会被序列化后,以消息的形式进行传递。所以,以这里的Category和Product为例,假如我有一个Product的实例,现在我把它序列化,此时会发生什么呢?他的属性Category也会被序列化,序列化这个Category属性时,又会发生什么呢?他的Products属性也要被序列化!!问题来了,我们最初的Product实例,肯定也包含在他的Category属性的Products中,所有又会被序列化。。。这样就死循环了。

    怎么办呢?办法很简单,至少将一个引用设为只读(设为只有get没有set)或不可序列化(为属性标注SerializationIgnoreAttribute)。在这个Category和Product的关系中,比较合理的是将Category.Products属性设为只读,代码如下:

[MappingName("Categories")] public interface Category : Entity { [PrimaryKey] int CategoryID { get; } [SqlType("nvarchar(15)")] string CategoryName { get; set; } [SqlType("ntext")] string Description { get; set; } byte[] Picture { get; set; } [FkQuery("Category", OrderBy = "{ProductName}", Contained = true, LazyLoad = true)] [SerializationIgnore] Product[] Products { get; set; } }

    此时,序列化Category时,就不会序列化他的Products,从而就能避免序列化的死循环。也就能正常用于分布式系统了。

0
相关文章