本文共 10632 字,大约阅读时间需要 35 分钟。
在这个小应用中,要用到webservice,因此简单介绍一下webservice。在实际应用中从客户端传送信息至服务端,使用webservice是一个不错的方法,它是一种构建应用程序的普遍模型,可以在任何支持网络通信的操作系统中实施运行。NET平台内也建立了对Web Service的支持,包括Web Service的构建和使用。NET Framework本身就全面支持Web Service,包括服务器端的请求处理器和对客户端发送和接受SOAP消息的支持。因此不需要其他的工具或者SDK就可以完成Web Service的开发了。
那么下面我们看看如何在服务器统计用户的在线时间。
环境:visual studio 2008;.net framework 2.0;Oracle 10g
功能实现:有两个表usertable a,userinfotable b, a存放用户基本固有信息,b表存放用户使详细信息及时间。当用户上线时程序中的webservice上传一次用户启动时间,当用户下线程序中webservice再次发送用户停止使用时间,进行保存,记录了一次用户使用时间,方便进行后续处理。
设计过程如下:
一、数据库设计
1、设计数据表
字段 | 类型 | 说明 |
id | integer | 表id,自增序列,主键 |
usersequence | varchar2(100) | 用户QQ号码,非空,唯一 |
uip | varcha2r(50) | 用户ip地址,从客户端获取 |
uaddress | varchar2(100) | 用户所在地址,从客户端根据ip获取 |
usystem | varcar2(32) | 用户使用的操作系统的位数,从客户端获取 |
useraddtime | date | 用户注册时间,也就是第一次插入数据的时间 |
字段 | 类型 | 说明 |
id | integer | 表id,自增序列,主键 |
consumerid | integer | 用户id,外键,usertable表userid关联 |
ustarttime | date | 用户本次启动软件时间 |
uendtime | date | 用户本次关闭软件时间 |
usertotaltimes | integer | 用户使用累计时间 |
useraddtime | date | 用户最后一次使用时间 |
2、详细SQL
(1)、创建表,序列
create table usertable ( id INTEGER not null, usersequence varchar2(100), uip varchar2(50), uaddress VARCHAR2(100), usystem VARCHAR2(32), useraddtime date ) create table userinfotable ( id INTEGER not null, consumerid INTEGER, ustarttime date, uendtime date, usertotaltimes number(30), useraddtime date ) CREATE SEQUENCE USERTABLE_SEQUENCES INCREMENT BY 1 START WITH 1 MAXVALUE 9999999999999999999 CREATE SEQUENCE USERINFOTABLE_SEQUENCES INCREMENT BY 1 START WITH 1 MAXVALUE 9999999999999999999
(2)、存储过程
开启qq时发送信息的存储过程
create or replace procedure startqqprocedure (qq in varchar2,ip in varchar2,address in varchar2,systemname in varchar2) as userid number; infoid number; begin select count(a.id) into userid from usertable a where a.usersequence=qq; if userid >0 then update usertable a set a.uip =ip,a.uaddress=address,a.usystem=systemname where a.usersequence = qq; else select usertable_sequences.nextval into userid from dual; insert into usertable (id,usersequence,uip,uaddress,usystem,useraddtime) values(userid,qq,ip,address,systemname,sysdate); end if; insert into userinfotable(id,consumerid,ustarttime,uendtime,usertotaltimes,useraddtime) values(userinfotable_sequences.nextval,userid,sysdate,sysdate,0,sysdate); commit; exception when others then rollback; end startqqprocedure;
关闭qq时发送信息的存储过程
create or replace procedure closeqqprocedure (qq in varchar2,ip in varchar2,address in varchar2,systemname in varchar2) as userid number; begin select count(a.id) into userid from usertable a where a.usersequence=qq; if userid >0 then update usertable a set a.uip =ip,a.uaddress=address,a.usystem=systemname where a.usersequence = qq; else select usertable_sequences.nextval into userid from dual; insert into usertable (id,usersequence,uip,uaddress,usystem,useraddtime) values(userid,qq,ip,address,systemname,sysdate); insert into userinfotable(id,consumerid,ustarttime,uendtime,usertotaltimes,useraddtime) values(userinfotable_sequences.nextval,userid,sysdate,sysdate,0,sysdate); end if; update userinfotable c set c.uendtime=sysdate,c.usertotaltimes= round(c.usertotaltimes)+ round(to_number(sysdate-c.ustarttime)*1440)where c.consumerid = userid; commit; exception when others then rollback; end closeqqprocedure;
二、代码实现
1、服务器端webservice实现。 数据库部分已完成,下面来进行程序实现,使用MVC设计模式,初步订三个类,webservice,DAO层QQWebServiceDao,执行sql语句SDProvider,实现各功能分离。 看看webservice如何写。using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using QQWebApp.WebWork.Dao; namespace QQWebApp.Service { ////// LMWebService 的摘要说明 /// [WebService(Namespace = "QQWebservice")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ToolboxItem(false)] public class QQWebservice: System.Web.Services.WebService { [WebMethod] //启动软件后 public bool FirstStart(string qq, string ip, string address,string systemname) { bool result = false; result = QQWebServiceDao.UploadStartCloseSoftInfo(qq, ip, address, systemname,true); return result; } [WebMethod] //关闭软件 public bool EndStop(string qq, string ip, string address,string systemname) { bool result = false; result = QQWebServiceDao.UploadStartCloseSoftInfo(qq, ip, address, systemname,false); return result; } }
那么c#如何执行存储过程呢?写数据库执行类,包括数据库连接,执行sql。
using System.Data; using System.Configuration; using System.Collections.Generic; using System.Data.OracleClient; using System.Diagnostics; using System; namespace QQWebApp.WebWork.Data { public class SDProvider { public static string GetConnectionString() { string conStr = "User ID=qqsoft;data source=orcl;password=sys"; return conStr ; } public static int RunProcedure(string storedProcName, IDataParameter[] parameters) { int result = 0; try { using (OracleConnection connection = new OracleConnection(GetConnectionString())) { connection.Open(); OracleCommand command = BuildQueryCommand(connection, storedProcName, parameters); result = command.ExecuteNonQuery();//返回受影响的行数 } } catch (Exception e) { Debug.Assert(false, e.Message); } return result; } private static OracleCommand BuildQueryCommand(OracleConnection connection, string storedProcName, IDataParameter[] parameters) { OracleCommand command = new OracleCommand(storedProcName, connection); command.CommandType = CommandType.StoredProcedure; foreach (OracleParameter parameter in parameters) { command.Parameters.Add(parameter); } return command; } }
这个类完成了存储过程的执行,参数的传递。
下面可以开始写DAO层,该层负责参数的处理,并调用SDProvider执行存储过程。using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using QQWebApp.WebWork.Data; using System.Data.OracleClient; namespace QQWebApp.WebWork.Dao public class QQWebServiceDao { public static bool UploadStartCloseSoftInfo(string qq, string ip,string address,string systemname,bool flag) { int result = 0; OracleParameter qqParameter = new OracleParameter("qq", OracleType.VarChar, 100); qqParameter.Value = qq; OracleParameter ipParameter = new OracleParameter("ip", OracleType.VarChar, 100); ipParameter.Value = ip; OracleParameter addressParameter = new OracleParameter("address", OracleType.VarChar, 100); addressParameter.Value = address; OracleParameter systemnameParameter = new OracleParameter("systemname", OracleType.VarChar, 100); systemnameParameter.Value = systemname; OracleParameter[] parameter = { qqParameter, ipParameter, addressParameter, systemnameParameter }; if (flag) { result = SDProvider.RunProcedure("startqqprocedure", parameter); } else { result = SDProvider.RunProcedure("closeqqprocedure", parameter); } return result > 0 ? true : false; } } }
这样就完成了服务端的程序。webservice、存储过程实现了融合使用。在这部分有几点注意的地方。
(1)、写存储过程中,定义的参数是不需要定义长度的。在存储过程中声明的变量不用加in|out。 (2)、DAO层中GetConnectionString()获取数据库的连接,这个连接字符串可以通过加密存放在Web.config中,更安全一些。 2、客户端调用 这样客户端的调用就很简单,首先要添加刚才写好的webservice,webservice写好发布之后有一个地址,假设是:,在本地添加引用。 声明并实例化, TestQQ.QQWebService service = new TestQQ.QQWebService (); 就可以调用service.看到FirstStart和endstop方法。不过在客户端还有一个任务,就是获取客户端的ip,省市地址和所使用的系统。获取ip参见,获取省市参见,获取使用的系统是32还是64位如下:public class OSDetectQuery { public static string QueryOSVersion() { try { ConnectionOptions oConn = new ConnectionOptions(); System.Management.ManagementScope oMs = new System.Management.ManagementScope("\\\\localhost", oConn); System.Management.ObjectQuery oQuery = new System.Management.ObjectQuery("select AddressWidth from Win32_Processor"); ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oMs, oQuery); ManagementObjectCollection oReturnCollection = null; try { oReturnCollection = oSearcher.Get(); } catch (System.Exception ex) { } string addressWidth = null; foreach (ManagementObject oReturn in oReturnCollection) { addressWidth = oReturn["AddressWidth"].ToString(); } return addressWidth; } catch (System.Exception ex) { return "32"; } } public static string OsVersion() { string queryos = QueryOSVersion(); string osVersion = Environment.OSVersion.ToString(); if (osVersion.Equals("Microsoft Windows NT 6.1.7600.0")) { if (queryos.Equals("64")) { return "Win7-64"; } if (queryos .Equals("32")) { return "Win7-32"; } return "Win7"; } else if (osVersion.Equals("Microsoft Windows NT 6.1.7600.0")) { if (queryos.Equals("64")) { return "Win7-64"; } if (queryos.Equals("32")) { return "Win7-32"; } return "Win7"; } return "WinXP"; } }
那么需要上传的客户端信息以获取完毕,直接调用service方法上传就可以了。
转载地址:http://lepyx.baihongyu.com/