Ansel's Blog

It would probably render the application more complex

博客园 首页 新随笔 联系 订阅 管理
Factory Pattern在.Net Remoting Architecture中的实现

混合法

混合法需要使用 RecordingsFactory SAO,它提供了创建 RecordingsManager CAO 的方法。(如果您不熟悉 SAO 示例,请参阅"使用服务器激活对象通过 .NET Remoting 实现 Broker"。)下面的类图表描述了总体解决方案。


1:混合法的结构

这种实现使用了 SAO 示例中所描述的共享接口法。IRecordingsManagerIRecordingsFactory 这两个接口位于客户端和服务器所共享的程序集中。IRecordingsFactory 有一个 Create 方法,它可以返回一个对象来实现 IRecordingsManager 接口。这是 AbstractFactory [Gamma95] 模式的一个例子。因为客户端只依靠接口,所以无需传送服务器代码。当客户端需要 IRecordingsManager 对象时,它调用 IRecordingsFactory 实例的 Create 方法。这样,客户端就可以控制 IRecordingsManager 对象的生存期,而无需实现该对象。共享程序集中的两个接口是:

IRecordingsManager.cs

以下示例显示了 IRecordingsManager 接口:

using System; 
using System.Data; 
public interface IRecordingsManager 
{ 
   DataSet GetRecordings(); 
} 

IRecordingsFactory.cs

以下示例显示了 IRecordingsFactory 接口:

using System; 
public interface IRecordingsFactory 
{ 
   IRecordingsManager Create(); 
} 

这些对象的服务器实现(RecordingsFactoryRecordingsManager)非常简单,并且包含在它们自己的、名为 Server 的程序集中。

RecordingsFactory.cs

该类扩展了 MarshalByRefObject,并实现了 IRecordingsFactory 接口:

using System; 
public class RecordingsFactory : MarshalByRefObject, IRecordingsFactory 
{ 
   public IRecordingsManager Create() 
   { 
      return new RecordingsManager(); 
   } 
} 

RecordingsFactory 对象是服务器激活对象。该实现只是对 RecordingsManager 类型调用 new。该 RecordingsManager 对象是在服务器上创建的,并且,不是作为 RecordingsManager 对象、而是作为 IRecordingsManager 接口返回的。利用这种机制,客户端就可以依赖于接口而不是实现。

RecordingsManager.cs

RecordingsManager 类所需要的唯一更改是,它现在实现的是 IRecordingsManager 接口。

using System; 
using System.Reflection; 
using System.Data; 
using System.Data.SqlClient; 
public class RecordingsManager : MarshalByRefObject, IRecordingsManager 
{ 
   public DataSet GetRecordings() 
   { 
      Console.WriteLine("Assembly: {0} - filling a request", 
         Assembly.GetEntryAssembly().GetName().Name); 
      String selectCmd = "select * from Recording"; 
      SqlConnection myConnection = new SqlConnection( 
         "server=(local);database=recordings;Trusted_Connection=yes"); 
      SqlDataAdapter myCommand =  
         new SqlDataAdapter(selectCmd, myConnection); 
      DataSet ds = new DataSet(); 
      myCommand.Fill(ds, "Recording"); 
      return ds; 
   } 
} 

HttpServer.cs

混合法中的服务器初始化代码用于为服务器激活的 RecordingsFactory 对象配置远程处理框架。激活方式与所使用的通道和协议无关,因此与以前一样(端口 8100 上的 HTTP 协议)。

using System; 
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels; 
using System.Runtime.Remoting.Channels.Http; 
public class HttpServer 
{ 
   static void Main(string[] args) 
   { 
      HttpChannel channel = new HttpChannel(8100); 
      ChannelServices.RegisterChannel(channel); 
      RemotingConfiguration.RegisterWellKnownServiceType( 
         typeof(RecordingsFactory), 
         "RecordingsFactory.soap", 
         WellKnownObjectMode.Singleton); 
      Console.ReadLine(); 
   } 
} 

在该代码中,RecordingsFactory 类型与 URL http://localhost:8100/RecordingsFactory.soap 相关联。

HttpClient.cs

客户端代码显示了这种方式的混合性质。首先使用 Activator.GetObject 方法从服务器检索 IRecordingsFactory 对象。然后,使用这个服务器激活对象来调用 Create 方法,以便实例化一个 IRecordingsManager 对象。这个新实例化的对象是在服务器上创建的,但它是一个远程对象。

using System; 
using System.Data; 
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels; 
using System.Runtime.Remoting.Channels.Http; 
public class HttpClient 
{ 
   [STAThread] 
   static void Main(string[] args) 
   { 
      HttpChannel channel = new HttpChannel(); 
      ChannelServices.RegisterChannel(channel); 
      IRecordingsFactory factory = (IRecordingsFactory) 
         Activator.GetObject(typeof(IRecordingsFactory), 
         "http://localhost:8100/RecordingsFactory.soap"); 
      Console.WriteLine("Client.main(): Factory acquired"); 
      IRecordingsManager mgr = factory.Create(); 
      DataSet ds = mgr.GetRecordings(); 
      Console.WriteLine("Recordings Count: {0}", 
         ds.Tables["recording"].Rows.Count); 
   } 
} 
23:31  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
远程对象的激活方式
2、远程对象的激活方式


在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。在Remoting中,远程对象的激活分为两大类:服务器端激活和客户端激活。

(1) 服务器端激活,又叫做WellKnow方式,很多又翻译为知名对象。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。.Net Remoting把服务器端激活又分为SingleTon模式和SingleCall模式两种。


SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维持其状态。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp.Net的状态管理,我们可以认为它是一种Application状态。


SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp.Net的状态管理,认为它是一种Session状态。


(2) 客户端激活。与WellKnown模式不同,Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。

(1) SingleTon模式


对于WellKnown对象,可以通过静态方法RemotingConfiguration.RegisterWellKnownServiceType()来实现:

RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(ServerRemoteObject.ServerObject),
                "ServiceMessage",WellKnownObjectMode.SingleTon);

(2)SingleCall模式


注册对象的方法基本上和SingleTon模式相同,只需要将枚举参数WellKnownObjectMode改为SingleCall就可以了。

RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(ServerRemoteObject.ServerObject),
                "ServiceMessage",WellKnownObjectMode.SingleCall);

(3)客户端激活模式


对于客户端激活模式,使用的方法又有不同,但区别不大,看了代码就一目了然。

RemotingConfiguration.ApplicationName = "ServiceMessage";
RemotingConfiguration.RegisterActivatedServiceType(
                typeof(ServerRemoteObject.ServerObject));

为什么要在注册对象方法前设置ApplicationName属性呢?其实这个属性就是该对象的URI。对于WellKnown模式,URI是放在RegisterWellKnownServiceType()方法的参数中,当然也可以拿出来专门对ApplicationName属性赋值。而RegisterActivatedServiceType()方法的重载中,没有ApplicationName的参数,所以必须分开。

2、客户端获得远程对象。

与服务器端相同,不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是WellKnown激活模式和客户端激活模式之间的区别,而对于SingleTon和SingleCall模式,客户端的实现完全相同。


(1) WellKnown激活模式

要获得服务器端的知名远程对象,可通过Activator进程的GetObject()方法来获得:

ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject(
              typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");

首先以WellKnown模式激活,客户端获得对象的方法是使用GetObject()。其中参数第一个是远程对象的类型。第二个参数就是服务器端的uri。如果是http通道,自然是用http://localhost:8080/ServiceMessage了。因为我是用本地机,所以这里是localhost,你可以用具体的服务器IP地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名,即ApplicationName属性的内容。

(2) 客户端激活模式


如前所述,WellKnown模式在客户端创建对象时,只能调用默认的构造函数,上面的代码就说明了这一点,因为GetObject()方法不能传递构造函数的参数。而客户端激活模式则可以通过自定义的构造函数来创建远程对象。


客户端激活模式有两种方法:


1) 调用RemotingConfiguration的静态方法RegisterActivatedClientType()。这个方法返回值为Void,它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。

 RemotingConfiguration.RegisterActivatedClientType(               
                typeof(ServerRemoteObject.ServerObject),
                "tcp://localhost:8080/ServiceMessage");
 ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();

2) 调用进程Activator的CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的GetObject()不同的是,它要在客户端调用构造函数,而GetObject()只是获得对象,而创建实例是在服务器端完成的。CreateInstance()方法有很多个重载,我着重说一下其中常用的两个。


a、 public static object CreateInstance(Type type, object[] args, object[] activationAttributes);

参数说明:
type:要创建的对象的类型。
args :与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 args 为空数组或空引用(Visual Basic 中为 Nothing),则调用不带任何参数的构造函数(默认构造函数)。
activationAttributes :包含一个或多个可以参与激活的属性的数组。

这里的参数args是一个object[]数组类型。它可以传递要创建对象的构造函数中的参数。从这里其实可以得到一个结论:WellKnown激活模式所传递的远程对象类,只能使用默认的构造函数;而Activated模式则可以用户自定义构造函数。activationAttributes参数在这个方法中通常用来传递服务器的url。

假设我们的远程对象类ServerObject有个构造函数:

            ServerObject(string pName,string pSex,int pAge)
            {
                name = pName;
                sex = pSex;
                age = pAge;
            }

那么实现的代码是:

            object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};
            object[] objs = new object[3];
            objs[0] = "wayfarer";
            objs[1] = "male";
            objs[2] = 28;
            ServerRemoteObject.ServerObject = Activator.CreateInstance(
                typeof(ServerRemoteObject.ServerObject),objs,attrs);
可以看到,objs[]数组传递的就是构造函数的参数。


b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);


参数说明:
assemblyName :将在其中查找名为 typeName 的类型的程序集的名称。如果 assemblyName 为空引用(Visual Basic 中为 Nothing),则搜索正在执行的程序集。
typeName:首选类型的名称。
activationAttributes :包含一个或多个可以参与激活的属性的数组。

参数说明一目了然。注意这个方法返回值为ObjectHandle类型,因此代码与前不同:

            object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};           
            ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject",
                                   "ServerRemoteObject.ServerObject",attrs);
            ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();

这个方法实际上是调用的默认构造函数。ObjectHandle.Unwrap()方法是返回被包装的对象。


说明:要使用UrlAttribute,还需要在命名空间中添加:using System.Runtime.Remoting.Activation;

10:39  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
2005-7-26
NET Web services vs. remoting: Which one will work best for your app?
Microsoft has made a tremendous amount of noise about building applications with Web services, and its .NET Framework simplifies the task of working with them. But while Web services represent a great way to build applications, they are ideally suited for clients outside the firewall calling components on your server over the Internet.
advertisement
IBM SWG


If both your clients and components are inside the firewall, Web services may work fine; however, all of your data travels through a Web server, which can slow performance. To speed things up, Microsoft provides a binary mechanism called remoting.

Let's take a look at how remoting works, and I'll share some code examples that show you how to set it up in a sample Web service.

How Web services work with .NET
For a brief explanation on how Web services work, and specifically how they work in .NET, check out this sidebar.

.NET remoting
While Web services are arguably the best way for clients outside of your organization to access components, what about components within your organization? Many companies are building Web services and using them internally. There is nothing wrong with this approach, but it doesn't provide the best performance. If components are created in .NET and the client applications are .NET, you can place components on shared servers and access them via remoting.

Remoting is the .NET technology that replaces DCOM allowing you to communicate between a client application and components in a binary format. As a result, remotable components are faster than Web services. However, creating remotable components is more difficult because you must add additional code to your components. This code isn't much more complicated than its Web service counterpart, but you cannot directly instantiate a remote component. Instead, you must create a host application that instantiates the component and listens for requests. The good news is that this host can be a Windows service, a Windows application, a console application, or anything that can run and hold the object open.

Not only do you have to create a host application, you must also make several decisions about the remotable object, such as which channel to use. .NET supports both HTTP and TCP channels. The HTTP channel actually uses the SOAP protocol to transport messages to and from remotable objects; this means all messages are serialized to XML. The TCP channel uses a binary stream to transport the messages.

Next, you must choose between two activation modes: Singleton and SingleCall. Singleton types have only one instance of an object at any time. All client requests are serviced by that single instance. This allows you to "share" data between requests or, more likely, maintain state between requests. SingleCall types, on the other hand, create a new instance of the object for each client request. SingleCall objects are more like Web services because they are stateless and are created and destroyed for each request.

.NET is architected in such a way that remotable components can change channels without being recompiled. You can place the channel information in a configuration file and change from TCP to HTTP or vice versa without recompiling the application. Similarly, you can change a configuration file for the client to match the channel that the host is using.

Quick code comparisons
To see some quick examples of a Web service and a remotable object with host, I'll use the example I used in a previous article in which I created a simple Web service. The entire code for the Web service follows:
 
<%@ WebService Language="VB" Class="ConvertMoney" %>
Imports System.Web.Services
<WebService()>Public Class ConvertMoney
Inherits WebService
<WebMethod()>Public Function _
PoundsToDollars(BritishPounds As Double) As Double
Return BritishPounds * 1.44
End Function
End Class

 

Here is the code to implement the same thing with a remotable component:
 
Public Class ConvertMoney
Inherits System.MarshalByRefObject
Public Function _
PoundsToDollars(ByVal BritishPounds As Double) As Double
Return BritishPounds * 1.44
End Function
End Class

 

The component looks simpler. In fact, the only difference is that it inherits from System.MarshalByRefObject. But remember, you need to build a host application that instantiates the object and listens for requests. The code for the host object could look like this:
 
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp
Imports RemoteConvertMoney
Module Module1
Sub Main()
Dim tcpChannel As New TcpChannel(7777)
ChannelServices.RegisterChannel(tcpChannel)
Dim ChangeMoney As New ConvertMoney
RemotingServices.Marshal(ChangeMoney, "ConvertMoney")
Console.ReadLine()
End Sub
End Module

 

In this case, the host application is a console application. You start the application and it launches a console application and creates the object. The console application runs until someone presses the [Enter] key, and the object is available until needed.

As you can see, the amount of work required to create the remotable component is more than the Web service.

Make the choice
There is no absolute answer to whether you should choose Web services or remoting in most cases. If your entire distributed application is inside your organization firewall and performance is critical, remoting via the TCP channel is the best choice. If the entire application is inside the firewall and performance isn't as critical, or if you want to keep things as simple as possible, Web services is a better choice.

But, if you need to allow access to clients other than .NET, you'll need to use Web services regardless of whether or not the client is inside or outside the firewall. In the end, the choice is left to the developer, so you'll need thorough knowledge of both technologies to make a proper decision.
0:34  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
Web services in .NET
Web services, called XML Web services by Microsoft, are the components that are instantiated via HTTP. Data is passed to, and received from, Web services using HTTP and SOAP, which is clear text and based upon XML. Thanks to Web services, passing data between different operating systems on different platforms has been simplified.

    Web services use HTTP to communicate, and this requires a Web server. Requests must be turned into SOAP messages that are sent to the Web server. There, they are processed, the object is instantiated, the method is executed, and the data is placed in an XML format to be returned to the client. The client application processes the XML as necessary.

    Given this scenario, it is no great surprise that Web services are slow when compared to direct binary access of objects. Without Web services, data does not have to be serialized to XML and deserialized on the client. Requests and returns do not have to flow through a Web server.

    Of course, Web services do offer advantages. First, they can be called by almost any client. The client does not have to be a .NET application. In fact, the client machine does not need to be running a Windows operating system. Second, because Web services use SOAP, the data flows across firewalls easily; all data is passed as XML. Finally, as far as .NET is concerned, the .NET Framework makes it incredibly easy to create Web services, and you can do so with just a few lines of code.
0:04  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
2005-7-25
Building Distributed Apps? Use XML Web Services, Not Remoting (Mostly)

If you have been wondering whether to use XML Web services or .NET Remoting, here's a simple answer: Use XML Web services most of the time. XML Web services are the same as marshal-by-value .NET Remoting, but using them is much easier than using Remoting from scratch.

Marshal-by-value remoting (XML Web services) means that you get XML-serialized data from your remote server. Sometimes, you may need dynamic event behavior or you may not want to move massive amounts of data and need a little more control. In this instance, you peel back the XML Web services layer and start building directly on top of .NET Remoting with marshal-by-reference objects and event sinks. Mostly not, though.

This article looks at the basic technologies that support XML Web services and provides a brief demonstration of how to produce and consume Web services.

XML Web Services Will Do

XML Web services in .NET are built on top of .NET Remoting. For all intents and purposes, a Web service is marshal-by-value .NET Remoting. The rumor mill also suggests that .NET Remoting may be completely concealed by XML Web services in the future, making advanced features of Remoting like event sinks available using Web services.

I hope you are more comfortable with XML Web services. Now, when you have to choose between Remoting and Web services, you are prepared to make a decision. Most of the time when you create distributed applications, XML Web services will do.

22:18  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
XML Web services .NET Remoting and System.NET Communication Guidelines
1. An XML Web Service call is essentially a SOAP message sent over the Http Protocol

2. .NET Remoting is a communication infrastructure that provides access to remote objects over the TCP protocol, Http protocol or some other custom protocol

3. XML Web Services uses SOAP (Simple Object Access Protocol) which is an XML message to communicate over the widely used Http protocol.

4. .NET Remoting provides object services over the Http or TCP protocol. .NET Remoting could be a SOAP message over a Http protocol (similar to XML Web service) or a TCP protocol or a Binary Formatted message over the TCP Protocol or Http Protocol.

5. When objects are remoted over a TCP Protocol using Binary Formatting or Encoding you have the best performance over any .NET Remoting Service or XML Web service.

6. If you intend to send SOAP messages over the Http protocol, do not use .NET Remoting, use XML Web services. The medium is the same in both instances and XML Web services deliver more speed than .NET Remoting service using SOAP Formatting over a Http protocol.

7. Using IIS as a Host or server offers scalability to both Remoted objects and XML Web Services. XML Web Services use IIS (Internet Information Server) as a Host and .NET Remoting can use IIS, Windows Services, Windows Form, Console Application as a Host or Server.

8. You can build your own interprocess communication solution using classes from the System.NET namesapce.

9. Using IIS as a host for XML Web services or .NET Remoting service offers security features like authentication and also state management.

10. Binary Formatting over the TCP protocol requires additional ports other that port 80 (which IIS uses) to be opened on your web server. These additional ports could pose security considerations.

11. Using .NET Remoting offers some flexibility for the activation of objects (they can be activated on the server or client), object life time management using leases and object instantiation management (SingleCall or Singleton modes.)

12. .NET Remoting offers access to a richer object oriented programming model than .XML Web services.

13. XML Web services offers a richer set of options for formatting SOAP messages than SOAP Formatting in a .NET Remoting Context.

14. XML Web services uses SOAP to communicate between two computers and is better suited for exchanging messages with applications not built with .NET while .NET Remoting is optimized for exchanging messages between .NET clients.
22:11  |  固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | .NET FRAMEWORK
设计 .NET 应用程序

升级到 Microsoft .NET

Paul D. Sheriff
PDSA, Inc.
2002年4月

出处:Microsoft

摘要:本文概要介绍 .NET 应用程序中的各种典型物理结构之间的区别,这些结构已被证明是很有用的。针对每种结构介绍了其适用方案、实现方式和优缺点。本文同时介绍了两层、三层和 N 层应用程序。

注意: 本文所介绍的应用程序设计问题在 MSDN? 的 Building Distributed Applications with .NET(英文)部分中进行了更深入的讨论。

目标

  • 了解 Microsoft? .NET 应用程序的典型结构。
  • 了解在每种结构内进行开发的优缺点。

前提条件

  • 熟悉 .NET 开发(包括 Web 开发和桌面开发)。
  • 熟悉编程概念(包括类和属性)。
  • 熟悉各种结构(包括多层和多服务器结构)。

目录

两层应用程序结构
使用 XML Web Service 的三层应用程序
使用 .NET Remoting 的三层应用程序
逻辑 N 层应用程序
使用 XML Web Service 的 N 层应用程序
其他 N 层应用程序技术
迁移 Visual Basic 6.0 的 N 层应用程序
小结

两层应用程序结构

典型的两层应用程序是使用 ADO.NET 直接与数据库服务器(如 Microsoft SQL Server?)进行通信的客户端应用程序(参见图 1)。除 ADO.NET 外,在客户端应用程序和数据库之间没有任何其他层。有关 ADO.NET 的详细信息,请参阅 .NET 框架文档、本系列的其他文章或使用 MSDN 搜索引擎。

图 1:两层应用程序包括客户端应用程序和数据存储(如 Microsoft SQL Server)

何时使用两层结构

两层应用程序适用于没有或只有少量窗体的小型应用程序。对于使用本文中介绍的其他 N 层技术的应用程序,其原型也可算是两层应用程序。但是,两层应用程序不太适用于企业环境,因为开发和维护的时间及成本不好控制。

典型的实现方式

开发两层应用程序时可以采用多种技术。所有技术均使用 ADO.NET、一个客户端界面(如桌面或基于 Web 的应用程序)和一个数据库(如 SQL Server)。要使用两层应用程序结构,可以采用以下方式:

  • 使用数据绑定技术将 ADO.NET 数据集直接与控件连接。
  • 编写代码以访问 ADO.NET 对象,从而手动将数据加载到用户界面的控件中。
  • 使用上述两种技术的组合。
  • 使用上述任何技术直接在窗体上编写业务规则代码。

优点

两层应用程序具有以下优点:

  • 因为可以使用数据绑定将 ADO.NET 数据集直接与用于构建用户界面的很多控件连接,所以开发工作就变得简单而快捷。这有助于迅速建立并运行应用程序的基本功能。
  • 只需查看窗体便可以浏览应用程序的全部代码,而无须同时查看窗体和另一个组件。

缺点

两层应用程序开发方法具有以下缺点:

  • 所有业务规则均包含在前端代码中。因而,如果需要更改业务规则,则必须更新全部客户端。除非能够进行自动更新,否则这种维护工作将十分繁琐。当然,如果使用 SQL Server,则可以将某些业务规则放到存储过程中,从而减少维护的时间和成本。
  • 尽管 SQL 可以在数据库结构和应用程序的其他部分之间提供某种程度的精简,但字段名称通常还是在源代码或控件属性中硬编码的。如果更改字段名称,则必须查找和替换应用程序中所有该字段的名称。如果使用了数据绑定,还必须检查所有窗体并更改属性。
  • 很多代码(如 SQL 语句和业务规则)常常在应用程序中重复出现,这是因为不同的窗体使用了某些相同的表。这使得此类应用程序的维护非常困难,因为如果需要更改表或字段的名称,则必须在多个位置进行更改,同时还需要在多个位置进行额外的回归测试。
  • 如果数据源发生变化,则对用于将数据加载到数据集的代码的更改将更加困难。例如,如果原来使用文本文件存储数据,然后又希望转换到 SQL Server,其访问方式是截然不同的。此外,要将数据加载到应用程序的数据集,还有很多地方都需要更改代码。

使用 XML Web Service 的三层应用程序

另一种设计方式是使用 XML Web service,将数据库的访问单独分给另一个组件,该组件将把数据返回到前端应用程序。图 2 显示了这种设计方式。

有关使用 XML Web services 开发三层应用程序的详细信息,请使用 MSDN 搜索引擎。


图 2:使用 XML Web service 将数据库层与前端代码分离

何时使用此技术

使用 XML Web service 的三层应用程序适用于基于 Web 的应用程序或 Microsoft Windows? 应用程序。如果需要桌面应用程序的丰富功能,而用户连接自多个不同的位置,并通过 HTTP 界面访问数据,则很适合使用此技术。

典型的实现方式

要创建三层/XML Web service 应用程序,通常采用以下开发技术:

  • 所有 SQL 驻留在 XML Web service 中。在服务器上构建数据集,并将其作为 XML 流返回到客户端,它们在这里又可以重新被构建为数据集。
  • 可以将从 XML Web service 返回的数据集直接绑定到窗体的控件中。
  • 可以使用从 XML Web service 返回的数据集手动将数据加载到窗体的各种控件中。
  • 直接在窗体上编写所有业务规则的代码。

优点

使用 XML Web service 的三层应用程序具有以下优点:

  • 因为可以使用数据绑定将 ADO.NET 数据集直接与用于构建用户界面的很多控件连接,所以开发工作就变得简单而快捷。这有助于迅速建立并运行应用程序的基本功能。
  • 用户可以从能连接到 Internet(或 Intranet)的任何地方运行应用程序。
  • 数据库访问被单独分给自己的组件,这样就无需在前端代码中嵌入 SQL。
  • 连接信息只保留在 XML Web service 上,同样减少了客户端计算机的维护工作。
  • 可以在某个中心位置更新数据库访问层。如果对此层进行简单的代码更改,则无需重新向客户端分发组件。

缺点

此设计的缺点与典型的两层应用程序的缺点基本相同,因为它并没有分离业务规则,而只是分离了数据层。此外,表中的列名称也没有被提取到类中(将在下一节中介绍)。

  • 所有业务规则均包含在前端代码中。因而,如果需要更改业务规则,则必须更新全部客户端。除非能够进行自动更新,否则这种维护工作将十分繁琐。当然,如果使用 SQL Server,则可以将某些业务规则放到存储过程中,从而减少维护的时间和成本。
  • 所有字段名称均在源代码或控件属性中硬编码。如果更改字段名称,则必须查找和替换应用程序中所有该字段的名称。如果使用了数据绑定,还必须检查所有窗体并更改属性。
  • 通过 HTTP 界面进行访问比直接连接数据库要慢。
  • 如果用户无法访问 Internet(或 Intranet),则无法使用该应用程序。

使用 .NET Remoting 的三层应用程序

这种类型的应用程序结构与使用 XML Web service 的三层应用程序几乎完全相同。唯一的区别是使用 .NET Remoting 代替 XML Web service 来包装数据访问层。图 3 显示了这种设计方式。

有关 .NET Remoting 的详细信息,请参阅本系列的其他文章或使用 MSDN 搜索引擎。

图 3:在 LAN 环境中,可以使用 .NET Remoting 来包装数据访问层

何时使用三层 .NET Remoting 技术

使用 .NET Remoting 的三层应用程序适用于必须在 LAN 中的计算机之间分布的应用程序。这可能是出于业务原因,或者考虑到所涉及的工作成本,采用网络呼叫比较合理。

典型的实现方式

要创建这种应用程序,通常采用以下开发技术:

  • 所有 SQL 驻留在通过 Remoting 服务调用的组件中。在服务器上构建数据集,并将其作为 XML 流返回到客户端,它们在这里又可以重新被构建为数据集。
  • 将从 Remoting 组件返回的数据集直接绑定到窗体的控件中。
  • 使用从 Remoting 组件返回的数据集手动将数据加载到窗体的不同控件中。
  • 直接在窗体上编写所有业务规则的代码。

优点

使用 .NET Remoting 的三层应用程序与使用 XML Web service 的三层应用程序具有相同的基本优点。

  • 因为可以使用数据绑定将 ADO.NET 数据集直接与用于创建用户界面的很多控件连接,所以编写三层应用程序就变得简单而快捷。这有助于迅速建立并运行应用程序的基本功能。
  • 用户可以从能连接到 LAN 或 WAN 的任何地方运行应用程序。
  • 数据库访问被单独分给另一个组件,这样就无需在前端代码中嵌入 SQL。
  • 可以在某个中心位置更新数据库访问层。如果在此组件中进行简单的代码更改,则无需重新向客户端分发组件。
    注意: 所有 N 层结构都具有此优点。

缺点

这种三层设计的缺点与使用 XML Web service 的三层设计的缺点相同。

  • 所有业务规则均包含在前端代码中。因而,如果需要更改业务规则,则必须更新全部客户端。除非能够进行自动更新,否则这种维护工作将十分繁琐。当然,如果使用 SQL Server,则可以将某些业务规则放到存储过程中,从而减少维护的时间和成本。
  • 所有字段名称均在源代码或控件属性中硬编码。如果更改字段名称,则必须查找和替换应用程序中所有该字段的名称。如果使用了数据绑定,还必须检查所有窗体并更改属性。
  • 通过网络从一个组件向另一个组件传输数据比直接连接数据库要慢。在 Intranet 方案中,.NET Remoting 的性能比 XML Web service 要好。而在 Internet 方案中,一般不使用 .NET Remoting。
  • 建立这种应用程序比建立两层应用程序或使用 XML Web service 的应用程序要复杂一些。

逻辑 N 层应用程序

使用 .NET 创建应用程序的最好方法是将所有逻辑进程分为不同的类。在典型的业务应用程序中,这通常包含业务规则组件、数据层组件和使用这些组件的前端代码。图 4 显示了这一方法。

有关设计 N 层应用程序的详细信息,请参阅本系列的其他文章或使用 MSDN 搜索引擎。


<图 4:将业务进程分解为不同的类,从而使应用程序更易于创建和维护

何时使用 N 层结构

逻辑 N 层开发策略适用于所有类型的应用程序。无论是小型、中型、大型应用程序,还是桌面或 Web 应用程序,效果都很好。

典型的实现方式

要创建这种应用程序,通常采用以下开发技术:

  • 使用 Windows 窗体或 Web 窗体创建前端用户界面。
  • 使用单独的类库项目创建业务规则组件。
  • 使用单独的类库项目创建数据层组件。此数据层使用类来包装对各个表的访问。应当使用类型化数据集;它们提供了灵活的数据集类,并且为表中的每个列提供了严格的类型检查功能。

优点

逻辑 N 层应用程序具有以下优点:

  • 将业务规则集中到易于创建、使用和重用的组件中,从而方便了开发和维护。
  • 提供了高级语言以开发业务规则,代替使用存储过程和有限的 SQL 语言来检查业务规则。
  • 将数据访问集中到组件中,从而减少了应用程序中的重复代码,每个需要访问特定表的窗体都使用相同的组件。
  • 如果使用类型化数据集,则可以使用智能感知功能来查询列名称,而不必记住它们。
  • 集中式数据访问例程有助于维护工作,因为对任何数据访问例程的更改都只需进行一次即可。
  • 可以随时将组件分离到不同的物理计算机上。这种灵活性使代码具有更好的可缩放性和集中性。

缺点

逻辑 N 层应用程序只有两个较大的缺点:

  • 开发时间稍长,因为必须构建单独的组件。
  • 需要跟踪的组件会多一些。这使其略显复杂,对于编程新手来说可能不太好理解。

使用 XML Web Service 的 N 层应用程序

图 5 显示了如何进行逻辑 N 层应用程序设计并将其分布于多台计算机的示例。在此图中,可以看到使用了 XML Web service 来访问数据层。类型化数据集通过 HTTP 层返回到业务规则层。然后,客户端应用程序可以将该数据集用于用户界面的数据显示。


图 5:将业务进程分离到单独的计算机中以利于部署和维护

何时使用此技术

如果需要桌面应用程序的丰富功能,而用户可能连接自很多远程位置,并且需要通过 HTTP 界面来获取数据,那么就可以采用这种 N 层 XML Web service 应用程序设计。将业务规则保留在客户端上有利于网络畅通,但如果这些规则更改频繁,则会增加一些维护更新工作。由于 .NET 可以复制新的 DLL 而无需注册,所以这些问题已经不象在以前的技术中那样严重。

这种方案也适用于基于 Web 的应用程序,其中由一台 Web 服务器提供数据,而由另一台 Web 服务器上的 Web 应用程序显示此数据。

典型的实现方式

要创建这种应用程序,通常采用以下开发技术:这些技术与逻辑 N 层应用程序中的技术相同。

  • 使用 Windows 窗体或 Web 窗体创建前端用户界面。
  • 使用单独的类库项目创建业务规则组件。
  • 使用单独的类库项目创建数据层组件。此数据层使用类来包装对各个表的访问。应当使用类型化数据集;它们提供了灵活的数据集类,并且为表中的每个列提供了严格的类型检查功能。

优点

使用 XML Web service 的 N 层应用程序具有多个优点,其中很多与逻辑 N 层应用程序相同。

  • 将业务规则集中到易于创建、使用和重用的组件中,从而方便了开发和维护。
  • 提供了高级语言以开发业务规则,代替使用存储过程和有限的 SQL 语言来检查业务规则。
  • 将数据访问集中到组件中,从而减少了应用程序中的重复代码,每个需要访问特定表的窗体都使用相同的组件。
  • 如果使用类型化数据集,则可以使用智能感知功能来查询列名称,而不必记住它们。
  • 集中式数据访问例程有助于维护工作,因为对任何数据访问例程的更改都只需进行一次即可。
  • 可以随时将组件分离到不同的物理计算机上。这种灵活性使代码具有更好的可缩放性和集中性。
  • 其他优点:集中式数据访问层。
  • 其他优点:应用程序的可扩展性 - 可以添加 Web 领域以处理用户对数据库的请求的大量负载。
  • 其他优点:用户可以通过 Internet 进行连接,但仍从桌面或基于 Web 的应用程序访问数据。

缺点

使用 XML Web service 的 N 层应用程序开发方法也有一些缺点。其中大部分与使用逻辑 N 层应用程序开发方案的缺点相同。

  • 开发时间稍长,因为必须构建单独的组件。
  • 需要跟踪的组件会多一些。这使其略显复杂,对于编程新手来说可能不太好理解。
  • 如果 XML Web service 不能正常工作,该应用程序将无法使用。

其他 N 层应用程序技术

当然,可以采用很多不同的技术来创建 N 层应用程序。例如,可以使用 .NET Remoting 在客户端层和业务规则层之间进行通信,如图 6 所示。


图 6:可以组合使用 .NET Remoting 和 XML Web services,为应用程序提供最佳的可缩放性和可维护性

使用 N 层技术开发应用程序后,还可以采用多种方法对其进行配置。可以组合使用 .NET 中的任何可用方法来分离应用程序的各层。

迁移 Visual Basic 6.0 的 N 层应用程序

程序员在以前版本的 Microsoft Visual Basic? 中使用 N 层技术已经有很多年了。如果有现成的 COM 组件,则可以很容易地为这些组件上加上 .NET 包装。之后,便可以获得如图 7 所示的结构。

有关在 .NET 中使用 COM 组件的详细信息,请参阅本系列的其他文章或使用 MSDN Web 站点 中的搜索引擎。

[img]http://www.knowlesys.com/technology/ms/design_.net_app.files/designnetapp07.gif[/img]

图 7:使用 .NET 可以方便地建立原有 COM 组件的接口

何时使用 Visual Basic 迁移技术

如果具有大量的 COM 组件代码,并且这些组件已经包含了您的业务规则和数据访问例程,则适合使用这种技术。因为可以利用很多现有代码,从而降低进入 .NET 框架的成本。

典型的实现方式

要创建这种应用程序,通常采用以下开发技术:

  • 使用 Windows 窗体或 Web 窗体创建前端用户界面。
  • 设置对原有 COM DLL 的引用。Microsoft .NET 自动为此 DLL 创建一个 .NET 包装,因此可以象对任何 .NET 组件那样访问其属性和方法。
  • 如果从该 DLL 中返回任何 ADO 记录集,则可以将它们转换为数据集,这是绑定到 .NET 控件的最简单的方法。

优点

在 COM 接口外加上 .NET 包装,可以在使用现有代码的同时充分利用 .NET 的新功能,从而缩短开发周期。

缺点

在 .NET 中使用 COM 包装具有以下缺点:

  • 其性能不如完全在 .NET 中编写的代码。
  • 可能需要额外的代码以将 ADO 记录集转换为 ADO.NET 数据集。

小结

在开发 .NET 应用程序时,可以采用的结构形式几乎是无限的。易于创建和维护的结构才是最好的。当然,还要考虑其他设计目标,包括可缩放性、可靠性和可管理性等。在 MSDN 中,您可以找到许多相关主题的白皮书。

 
2005-7-19
ADO.NET创建关联的范例

SqlConnection custConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind;");
SqlDataAdapter custDA = new SqlDataAdapter("SELECT * FROM Customers", custConn);

OleDbConnection orderConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" +
                                                "Data Source=c:\\Program Files\\Microsoft Office\\Office\\Samples\\northwind.mdb;");
OleDbDataAdapter orderDA = new OleDbDataAdapter("SELECT * FROM Orders", orderConn);

custConn.Open();
orderConn.Open();

DataSet custDS = new DataSet();

custDA.Fill(custDS, "Customers");
orderDA.Fill(custDS, "Orders");

custConn.Close();
orderConn.Close();

DataRelation custOrderRel = custDS.Relations.Add("CustOrders",
                              custDS.Tables["Customers"].Columns["CustomerID"],   
                              custDS.Tables["Orders"].Columns["CustomerID"]);

foreach (DataRow pRow in custDS.Tables["Customers"].Rows)
{
  Console.WriteLine(pRow["CustomerID"]);
   foreach (DataRow cRow in pRow.GetChildRows(custOrderRel))
    Console.WriteLine("\t" + cRow["OrderID"]);
}

posted on 2005-08-22 15:48  Ansel  阅读(1147)  评论(2编辑  收藏  举报