创建一个从数据库读入内容的远程对象
2008-03-20 21:43
441 查看
.NET Remoting提供了一个功能强大、高效的处理远程对象的方法,从结构上而言,.NET Remote对象非常适合通过网络访问资源,而又无需处理由基于SOAP的WebServices所带来的难题。.NET Remoting使用起来比Java的RMI简单,但要比创建Web Service难度大一些。
在本篇文章中,我们将创建一个从数据库读入内容的远程对象。文中还包括了一个忽略数据库功能的替补对象,以使没有数据库可以使用的读者仍然能够使用.NET Remoting。
第一步:创建共享库
依次点击“文件”->“新创建”->“工程”,选择创建一个C# Library,并将其命名为ResumeServerLibrary,然后点击OK按钮。这将创建一个我们的.NET Remote客户端和服务器端用来通讯的“共享命令集”。
正面是完整的代码,如果要跳过数据库访问部分,可以使用下面的代码替换ResumeLoader对象:
public class ResumeLoader : System.MarshalByRefObject
{
public ResumeLoader()
{
System.Console.WriteLine("New Referance Added!");
}
public Resume GetResumeByUserID(decimal userID)
{
return new Resume(1);
}
}
名字空间是对象所需要的。请记住,如果得到System.Runtime.Remoting.Channels.Tcp名字空间不存在的信息,请检查是否象上面的代码那样添加了对System.Runtime.Remoting.dll的引用。
using System;
using System.Runtime;
using System.Data.SqlClient;
我们为对象使用的名字空间是DotNetRemoteTest,下面的对象是MarshalByRefObject,在其中我们创建了一个引用和包括服务器端数据库操作全部完成所需要的所有工作。
namespace DotNetRemoteTest
{
public class ResumeLoader : System.MarshalByRefObject
{
private SqlConnection dbConnection;
public ResumeLoader()
{
this.dbConnection = new System.Data.SqlClient.SqlConnection();
this.dbConnection.ConnectionString =
"data source=GRIMSAADO2K;initial catalog=underground;integrated security=SSPI;pers" +
"ist security info=True;workstation id=GRIMSAADO2K;packet size=4096";
/*具体的连接字符串会有所不同,这超出了本篇文章的范围。如果不清楚如何创建一个数据库连接,请使用这一对象的另一个版本。*/
System.Console.WriteLine("New Referance Added!");
}
public Resume GetResumeByUserID(decimal userID)
{
Resume resume = new Resume();
try
{
dbConnection.Open();
SqlCommand cmd = new SqlCommand(
"SELECT ResumeID, UserID, Title, Body FROM Resume as theResume WHERE theResume.UserID="+ userID +""
, dbConnection
);
SqlDataReader aReader = cmd.ExecuteReader();
if(aReader.Read())
{
resume.ResumeID=aReader.GetDecimal(0);
resume.UserID=aReader.GetDecimal(1);
resume.Title=aReader.GetString(2);
resume.Body=aReader.GetString(3);
}
aReader.Close();
dbConnection.Close();
}
catch(Exception x) { resume.Title="Error:"+x; }
return resume;
}
}
Resume需要能够被串行化,以便能作为被远程调用的.NET Remote对象的返回类型,原因是该对象将被转换为通过网络传输的原始数据,然后在网络的另一端再被装配成一个对象。
该对象非常简单,为了使本篇文章看起来更简单,其中的构造器甚至使用缺省的内容初始化其中的一些域。
[Serializable]
public class Resume
{
private decimal resumeID, userID;
private String body, title;
public Resume(decimal resumeID)
{
this.ResumeID=resumeID;
this.UserID=1;
this.Body="This is the default body of the resume";
this.Title="This is the default Title";
}
public decimal ResumeID
{
get { return resumeID; }
set { this.resumeID=value; }
}
public decimal UserID
{
get { return userID; }
set { this.userID=value; }
}
public String Body
{
get { return body; }
set
{
this.body=value;
}
}
public String Title
{
get { return title; }
set
{ this.title=value; }
}
}//RESUME对象结束
}//DotNetRemoteTest名字空间结束
编译创建的工程,就会得到一个DLL文件,并可以在其他的工程中使用它。
第二步:创建Server对象
有几种方法可以创建Server对象,最直观的方法是下面的方法:在Visual Studio.NET中,依次点击“文件”->“新创建”->“工程”,选择创建一个“Command Line Application”(命令行应用程序),并将它命名为ResumeSuperServer。
最最重要的是,我们需要添加对刚才在第一步中所创建的DLL文件的应用,该应用程序才能正确地运行。依次点击“工程”->“添加引用”,然后通过点击“浏览”按钮添加一个对在第一步中所创建的DLL文件的引用。
为了使用.NET remote功能,必须通过选择“工程”->“添加引用”,添加对DLL文件的引用。在.NET标签中选择System.Runtime.Remoting.DLL,然后点击“OK”按钮。然后,需要象我们在第一步中那样添加对System.Runtime.Remoting.dll的引用。
下面的对象相当的简单和直观,我将就真正与.NET remoting相关的3行代码中的每一行进行解释。
TcpServerChannel是.NET remoting支持的二种信道类型中的一种,它将设置我们希望我们的对象对来自哪一个端口的请求进行回应,ChannelServices.RegisterChannel将把该端口号与操作系统中的TCP/IP栈绑定。
TcpServerChannel channel = new TcpServerChannel(9932);
ChannelServices.RegisterChannel(channel);
另一种可以设置的信道类型是HTTP,只要简单地使用System.Runtime.Remoting.Channels.Http名字空间中的HttpServerChannel对象即可搞定。使用HTTP和TCP信道之间的区别可以简单的归结为:如果应用程序是在局域网上运行,则最好使用TCP信道,因为它的性能要好于HTTP信道;如果应用程序是在互联网上运行,则有时候根据防火墙的配置,HTTP是唯一的选择。需要记住的是,如果使用了防火墙软件,则防火墙应该配置成允许TCP数据流量通过你为对象选择的端口。
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ResumeLoader),
"ResumeLoader", WellKnownObjectMode.SingleCall);
这行代码设置了服务中的一些参数和把欲使用的对象名字与远程对象进行绑定,第一个参数是绑定的对象,第二个参数是TCP或HTTP信道中远程对象名字的字符串,第三个参数让容器知道,当有对对象的请求传来时,应该如何处理对象。尽管WellKnownObjectMode.Single对所有的调用者使用一个对象的实例,但它为每个客户生成这个对象的一个实例。
完整的对象代码如下所示:
using System;
using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Data.SqlClient;
using DotNetRemoteTest;
namespace ResumeServerServer
{
public class ResumeSuperServer
{
public static void Main(String[] args)
{
TcpServerChannel channel = new TcpServerChannel(9932);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ResumeLoader),
"ResumeLoader", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Press Any Key");
System.Console.ReadLine();
}
}
}
编译这一程序并注意生成的.EXE文件的位置。
第三步:创建Remote客户端程序
ResumeClinet是我们为对在上面创建的ResumeSuperServer远和对象进行测试而创建的。要创建这一工程,可以依次点击“文件”->“创建”->“工程”,然后选择创建一个Console Application类型、名字为ResumeClient的工程名。象在第二步中那样,我们需要添加对在第一步中创建的DLL文件和System.Runtime.Remoting DLL的引用。
下面的代码中有二行对于.NET remoting而言是特别重要的。第一行创建了一个TCP客户端信道,该信道并不是绑定在一个端口上的;第二行获取了一个对远程的ResumeLoader对象的引用。Activator.GetObject方法返回一个对象类型的值,我们随后会将它返回的值赋予ResumeLoader。我们传给它的参数与在服务器工程中传递给RemotingConfiguration的参数非常地相似,第一个参数是对象类型的,第二个参数是远程对象的URI。
ChannelServices.RegisterChannel(new TcpClientChannel());
ResumeLoader loader = (ResumeLoader)Activator.GetObject(
typeof(ResumeLoader), "tcp://localhost:9932/ResumeLoader");
ResumeClient的全部代码如下所示:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using DotNetRemoteTest;
namespace ResumeClient
{
public class ResumeClient
{
public static void Main(string[] args)
{
ChannelServices.RegisterChannel(new TcpClientChannel());
ResumeLoader loader = (ResumeLoader)Activator.GetObject(
typeof(ResumeServer), "tcp://localhost:9932/ResumeLoader");
if(rs==null)
{ Console.WriteLine("Unable to get remote referance"); }
else
{
Resume resume = loader.GetResumeByUserID(1);
Console.WriteLine("ResumeID:"+ resume.ResumeID);
Console.WriteLine("UserID:"+ resume.UserID);
Console.WriteLine("Title:"+ resume.Title);
Console.WriteLine("Body:"+ resume.Body);
}
Console.ReadLine();//在能够看到结果前不让窗口关闭
}//END OF MAIN METHOD
}//END OF ResumeClient Object
}//END OF ResumeClientNamespace
测试
在数据库中创建一个具有如下结构的表:
Table Name-Resume
ResumeID, numeric (autonumber)
UserID, numeric
Title, Char(30)
Body, Text
双击我们在第二步中创建的Server.exe,然后双击在第三步中创建的Client可执行文件。如果一切正常的话,我们应该能够看到数据库中ResumeID的值为1的记录行。
总之,.NET Remoting使用起来很简单,而且为处理局域网甚至互联网范围内的资源提供了一个绝佳的方法
在本篇文章中,我们将创建一个从数据库读入内容的远程对象。文中还包括了一个忽略数据库功能的替补对象,以使没有数据库可以使用的读者仍然能够使用.NET Remoting。
第一步:创建共享库
依次点击“文件”->“新创建”->“工程”,选择创建一个C# Library,并将其命名为ResumeServerLibrary,然后点击OK按钮。这将创建一个我们的.NET Remote客户端和服务器端用来通讯的“共享命令集”。
正面是完整的代码,如果要跳过数据库访问部分,可以使用下面的代码替换ResumeLoader对象:
public class ResumeLoader : System.MarshalByRefObject
{
public ResumeLoader()
{
System.Console.WriteLine("New Referance Added!");
}
public Resume GetResumeByUserID(decimal userID)
{
return new Resume(1);
}
}
名字空间是对象所需要的。请记住,如果得到System.Runtime.Remoting.Channels.Tcp名字空间不存在的信息,请检查是否象上面的代码那样添加了对System.Runtime.Remoting.dll的引用。
using System;
using System.Runtime;
using System.Data.SqlClient;
我们为对象使用的名字空间是DotNetRemoteTest,下面的对象是MarshalByRefObject,在其中我们创建了一个引用和包括服务器端数据库操作全部完成所需要的所有工作。
namespace DotNetRemoteTest
{
public class ResumeLoader : System.MarshalByRefObject
{
private SqlConnection dbConnection;
public ResumeLoader()
{
this.dbConnection = new System.Data.SqlClient.SqlConnection();
this.dbConnection.ConnectionString =
"data source=GRIMSAADO2K;initial catalog=underground;integrated security=SSPI;pers" +
"ist security info=True;workstation id=GRIMSAADO2K;packet size=4096";
/*具体的连接字符串会有所不同,这超出了本篇文章的范围。如果不清楚如何创建一个数据库连接,请使用这一对象的另一个版本。*/
System.Console.WriteLine("New Referance Added!");
}
public Resume GetResumeByUserID(decimal userID)
{
Resume resume = new Resume();
try
{
dbConnection.Open();
SqlCommand cmd = new SqlCommand(
"SELECT ResumeID, UserID, Title, Body FROM Resume as theResume WHERE theResume.UserID="+ userID +""
, dbConnection
);
SqlDataReader aReader = cmd.ExecuteReader();
if(aReader.Read())
{
resume.ResumeID=aReader.GetDecimal(0);
resume.UserID=aReader.GetDecimal(1);
resume.Title=aReader.GetString(2);
resume.Body=aReader.GetString(3);
}
aReader.Close();
dbConnection.Close();
}
catch(Exception x) { resume.Title="Error:"+x; }
return resume;
}
}
Resume需要能够被串行化,以便能作为被远程调用的.NET Remote对象的返回类型,原因是该对象将被转换为通过网络传输的原始数据,然后在网络的另一端再被装配成一个对象。
该对象非常简单,为了使本篇文章看起来更简单,其中的构造器甚至使用缺省的内容初始化其中的一些域。
[Serializable]
public class Resume
{
private decimal resumeID, userID;
private String body, title;
public Resume(decimal resumeID)
{
this.ResumeID=resumeID;
this.UserID=1;
this.Body="This is the default body of the resume";
this.Title="This is the default Title";
}
public decimal ResumeID
{
get { return resumeID; }
set { this.resumeID=value; }
}
public decimal UserID
{
get { return userID; }
set { this.userID=value; }
}
public String Body
{
get { return body; }
set
{
this.body=value;
}
}
public String Title
{
get { return title; }
set
{ this.title=value; }
}
}//RESUME对象结束
}//DotNetRemoteTest名字空间结束
编译创建的工程,就会得到一个DLL文件,并可以在其他的工程中使用它。
第二步:创建Server对象
有几种方法可以创建Server对象,最直观的方法是下面的方法:在Visual Studio.NET中,依次点击“文件”->“新创建”->“工程”,选择创建一个“Command Line Application”(命令行应用程序),并将它命名为ResumeSuperServer。
最最重要的是,我们需要添加对刚才在第一步中所创建的DLL文件的应用,该应用程序才能正确地运行。依次点击“工程”->“添加引用”,然后通过点击“浏览”按钮添加一个对在第一步中所创建的DLL文件的引用。
为了使用.NET remote功能,必须通过选择“工程”->“添加引用”,添加对DLL文件的引用。在.NET标签中选择System.Runtime.Remoting.DLL,然后点击“OK”按钮。然后,需要象我们在第一步中那样添加对System.Runtime.Remoting.dll的引用。
下面的对象相当的简单和直观,我将就真正与.NET remoting相关的3行代码中的每一行进行解释。
TcpServerChannel是.NET remoting支持的二种信道类型中的一种,它将设置我们希望我们的对象对来自哪一个端口的请求进行回应,ChannelServices.RegisterChannel将把该端口号与操作系统中的TCP/IP栈绑定。
TcpServerChannel channel = new TcpServerChannel(9932);
ChannelServices.RegisterChannel(channel);
另一种可以设置的信道类型是HTTP,只要简单地使用System.Runtime.Remoting.Channels.Http名字空间中的HttpServerChannel对象即可搞定。使用HTTP和TCP信道之间的区别可以简单的归结为:如果应用程序是在局域网上运行,则最好使用TCP信道,因为它的性能要好于HTTP信道;如果应用程序是在互联网上运行,则有时候根据防火墙的配置,HTTP是唯一的选择。需要记住的是,如果使用了防火墙软件,则防火墙应该配置成允许TCP数据流量通过你为对象选择的端口。
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ResumeLoader),
"ResumeLoader", WellKnownObjectMode.SingleCall);
这行代码设置了服务中的一些参数和把欲使用的对象名字与远程对象进行绑定,第一个参数是绑定的对象,第二个参数是TCP或HTTP信道中远程对象名字的字符串,第三个参数让容器知道,当有对对象的请求传来时,应该如何处理对象。尽管WellKnownObjectMode.Single对所有的调用者使用一个对象的实例,但它为每个客户生成这个对象的一个实例。
完整的对象代码如下所示:
using System;
using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Data.SqlClient;
using DotNetRemoteTest;
namespace ResumeServerServer
{
public class ResumeSuperServer
{
public static void Main(String[] args)
{
TcpServerChannel channel = new TcpServerChannel(9932);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(ResumeLoader),
"ResumeLoader", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Press Any Key");
System.Console.ReadLine();
}
}
}
编译这一程序并注意生成的.EXE文件的位置。
第三步:创建Remote客户端程序
ResumeClinet是我们为对在上面创建的ResumeSuperServer远和对象进行测试而创建的。要创建这一工程,可以依次点击“文件”->“创建”->“工程”,然后选择创建一个Console Application类型、名字为ResumeClient的工程名。象在第二步中那样,我们需要添加对在第一步中创建的DLL文件和System.Runtime.Remoting DLL的引用。
下面的代码中有二行对于.NET remoting而言是特别重要的。第一行创建了一个TCP客户端信道,该信道并不是绑定在一个端口上的;第二行获取了一个对远程的ResumeLoader对象的引用。Activator.GetObject方法返回一个对象类型的值,我们随后会将它返回的值赋予ResumeLoader。我们传给它的参数与在服务器工程中传递给RemotingConfiguration的参数非常地相似,第一个参数是对象类型的,第二个参数是远程对象的URI。
ChannelServices.RegisterChannel(new TcpClientChannel());
ResumeLoader loader = (ResumeLoader)Activator.GetObject(
typeof(ResumeLoader), "tcp://localhost:9932/ResumeLoader");
ResumeClient的全部代码如下所示:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using DotNetRemoteTest;
namespace ResumeClient
{
public class ResumeClient
{
public static void Main(string[] args)
{
ChannelServices.RegisterChannel(new TcpClientChannel());
ResumeLoader loader = (ResumeLoader)Activator.GetObject(
typeof(ResumeServer), "tcp://localhost:9932/ResumeLoader");
if(rs==null)
{ Console.WriteLine("Unable to get remote referance"); }
else
{
Resume resume = loader.GetResumeByUserID(1);
Console.WriteLine("ResumeID:"+ resume.ResumeID);
Console.WriteLine("UserID:"+ resume.UserID);
Console.WriteLine("Title:"+ resume.Title);
Console.WriteLine("Body:"+ resume.Body);
}
Console.ReadLine();//在能够看到结果前不让窗口关闭
}//END OF MAIN METHOD
}//END OF ResumeClient Object
}//END OF ResumeClientNamespace
测试
在数据库中创建一个具有如下结构的表:
Table Name-Resume
ResumeID, numeric (autonumber)
UserID, numeric
Title, Char(30)
Body, Text
双击我们在第二步中创建的Server.exe,然后双击在第三步中创建的Client可执行文件。如果一切正常的话,我们应该能够看到数据库中ResumeID的值为1的记录行。
总之,.NET Remoting使用起来很简单,而且为处理局域网甚至互联网范围内的资源提供了一个绝佳的方法
相关文章推荐
- 6-2-1 字符串-字符串变量String-创建字符串变量-初始化字符串变量-字符串连接-输入字符串(单词、行)-对象变量的赋值-比较两个字符串是否同一个-比较两个字符串内容是否相同
- 在Oracle中创建用户数据库对象的一个好习惯
- oracle如何创建一个远程数据库上的某张表的同义词
- 编写一个文件,读取 src 下面day12包 下面的my.properties 文件,文件内容如下, className=day12.User 结合 IO、反射知识,完成 配置文件中对象的创建和方法调用。并编写方法,列举出 Student 类中所有的属性、
- 8.9 编写函数打开文件用于输入,将文件内容读入 string 类型的 vector 容器,每一行存储为该容器对象 的一个元素。8.10 重写上面的程序,把文件中的每个单词存储为 容器的一个元素
- iOS 怎么将自己创建的一个对象存入数据库sqlite,例如:Person??
- 编写程序从标准输入设备读入的元素数据建立一个int型vector对象,然后动态创建与该vector大小一致的数组,把vector对象的所有元素复制给该数组
- jquery创建一个新的节点对象(自定义结构/内容)的好方法
- Android 创建一个私有的数据库(内容提供者)
- 结合网上内容,分享一个,java用for循环创建i个对象,的方法
- Remoting创建远程对象的一个实例:
- 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)
- SQLServer获得所有用户存储过程、根据存储过程名称获得内容、获得数据库对象创建脚本
- 创建一个Session对象,用javascript弹出内容
- jquery创建一个新的节点对象(自定义结构/内容)的好方法
- 手动写一个将数据库中查询的内容封装到对象中
- 内容提供者ContentProvider →采用layoutInflater打气筒创建一个view对象
- ADO 实例《创建一个临时数据库 创建一个临时数据表 GridView1绑定内容 以及Dataset_的使用》
- java创建一个子类对象是会调用父类的构造方法会不会创建父类