刚刚.Net相关知识技术互动平台(绿色天堂)
.Net知识技术交流、探讨、请教与共享(Visual Studio.Net、Asp.Net、VB/C#、.NetWindows应用程序、Windows服务、Socket通信、GIS、ArcGIS、JavaScript、Sql Server和Oracle等)
posts - 73,  comments - 472,  trackbacks - 38
    已经隔了好长时间了,我向广大博友先道歉,最近工作比较忙,这片文档也是今天抽出时间来完成的,不过我还是会像现在这样抽时间来完成这个系列。
    在《Web服务初探:用Demo学Web服务系列(4)——改变所调用的Web服务》这篇随笔中我们讲了如何使用Web Services的Soap消息的SoapHeader来传递参数,为此我们改变了在《Web服务初探:用Demo学Web服务系列(3)——用C/S程序调用Web服务》中的C/S程序和《Web服务初探:用Demo学Web服务系列(2)——编写一简单的Web服务》中编写的WebService方法。这次我们来讲解一下将方法改变成从数据库中来验证用户的登录,这个只需要改变《Web服务初探:用Demo学Web服务系列(4)——改变所调用的Web服务》中的WebService而不用再变动已经做过更改的C/S程序。
    在讲解之前,我要提到的一点是在我们的《ASP.NET AJAX技术联盟》QQ群中有人问到用Web Services如何实现三层结构。我们来看看三层结构的情况如下:

底层:数据库服务器(存放数据库执行SQL语句);中间层:Web Services(用来接收参数后执行组织出需要执行的SQL语句,发送给底层,并将SQL语句执行后的结果用Soap消息返回给应用层);应用层:各种C/S程序软件或B/S程序软件(为了适合用户各种需求而设计的必须达到的某些功能或模块的程序,为了实现所需的功能和模块,产生一些参数发送给中间层,并对返回数据处理和显示)。

    相信说道这里应该有人明白了这三个层次的简单分工了,也应该知道哪些代码应该放到哪个层中去写来实现上述的层次。当然不可否认,这里的分层理论说明的并不是很科学,比如:中间层和应用层之间有很多模糊的地方,对于界面的风格,按钮的设计等等类似的功能风格设计可以不用写在中间层,而放到应用层。对于数据库的访问则放在中间层,应用层并不对数据库做直接读写工作。(这只是个人的见解,如果还有人有更好的发方法也希望互相交流。)
    好了,言归正传,我们是如何让一个WebService访问数据库的呢?我们这里有两个方法。这两个方法也是.NET本身提供给我们的ADO.NET的方法,一样适用于在WebService中使用,一种是连接模式,一种是断开模式。
我们首先来看连接模式,在下一篇随笔中再来看看断开模式。按照惯例,我们仍然将改变前后的WebService给大家粘贴出来。
改变前的WebService
 1using System;
 2using System.Web;
 3using System.Web.Services;
 4using System.Web.Services.Protocols;
 5
 6public class MyServiceClassHeader : SoapHeader
 7{
 8    public string UsN;
 9    public string PaW;
10}

11[WebService(Namespace = "http://tempuri.org/")]
12[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
13public class MyServiceClass : System.Web.Services.WebService
14{
15    public MyServiceClass()
16    {
17
18        //如果使用设计的组件,请取消注释以下行 
19        //InitializeComponent(); 
20    }

21
22    public MyServiceClassHeader MSCH;
23
24    [WebMethod]
25    [SoapHeader("MSCH",Direction = SoapHeaderDirection.In)]
26    public string Login()
27    {
28        if (MSCH != null)
29        {
30            if (MSCH.MustUnderstand)
31            {
32                string UserName = MSCH.UsN;
33                string PassWord = MSCH.PaW;
34                if (UserName == "Micky" && PassWord == "micky0")
35                {
36                    return "登录成功!";
37                }

38                else
39                {
40                    return "登录错误!";
41                }

42            }

43            else
44            {
45                return "消息头不是必懂的!";
46            }

47        }

48        else
49        {
50            return "无头消息!";
51        }

52    }

53}
改变后的WebService(实际上我们是改变并增加了访问数据库的代码)
改变后的WebService
因为上面代码太长,所以我们把代码折叠了。这里当然是要在数据库中建立一张表,通过代码的“Selece”语句中的字段。注:本来是想使用Access数据库,但在Visual Studio.Net2005中有简易的Sql Server2005,所以就用的Sql Server2005,您也可以使用Access建立数据库,表中的字段都是一样的,唯一的区别是在引用、代码和Web.Config中的区别,别忘了把数据库文件也放到工程系统文件夹“App_Data”下面,我们来看看引用和Web.Config的区别:
一、使用Sql Server2005数据库需要添加的引用:
using System.Data.SqlClient;
二、使用Access2003数据库需要添加的引用:
using System.Data.OleDb;
三、无论使用哪个数据库都要添加的引用(为的是访问此WebService中的Web.Config):
using System.Web.Configuration;
using System.Configuration;
四、使用Sql Server2005数据库需要添加改变的Web.Config:
1<configuration>
2    <appSettings/>
3  <connectionStrings>
4    <add name="WSConStringSQL" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\WSDemoDB.mdf;Integrated Security=True;User Instance=True"
5      providerName="System.Data.SqlClient" />
6  </connectionStrings>
7    <system.web>
五、使用Access2003数据库需要添加改变的Web.Config:
1<configuration>
2    <appSettings/>
3  <connectionStrings>
4    <add name="WSConStringSQL" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\WSDemoDB.mdb;Persist Security Info=True"
5      providerName="System.Data.OleDb" />    
6  </connectionStrings>
7    <system.web>

别忘了在数据库中输入一条数据哦。使用Access2003数据库时记得将代码中的SqlConnection换为OleDbConnection,SqlCommand换为OleDbCommand,SqlDataReader换为OleDbDataReader。
    其实今天Demo和WebService的本身知识关系不是很大,而与ADO.NET2.0的关系却很大,所以就不过到解释了,大家可以根据代码和相关书籍研究。

    你仍然可以通过前面的C/S程序,把代理类更新一下,然后运行测试。输入你数据库中所给的数据,再输入一个数据库中没有的数据,看看是什么结果呢?
    顺便再说一句:这个就是一个简单的三层结构,当然这个WebService编写的不是很通用,但结构却是三层结构的特征,你能理解了吗?

转载本文说明(以下简称本说明):必须遵守《刚刚网络作品版权声明》,再转载。"本说明、作者、作者博客网址及作者博客坐落,本文中提及的各种说明、备注或附录性文字"必须被转载,且不得改变其原有内容和要表达的意图!
作者:刚刚   作者博客网址:http://lijigang.cnblogs.com/   作者博客坐落在博客园
把握现实生活,培养自身能力
掌握新型技术,提高自我力量

posted on 2006-11-14 00:07 刚刚 阅读(2551) 评论(23)  编辑 收藏 所属分类: WebServices XML技术

FeedBack:
2006-11-14 10:28 | Hunts.C      
一大早起来就把你的系列实践了一遍,有收获,谢谢刚刚!
继续加油!:)
  回复  引用  查看    
2006-11-14 11:27 | Riancy [未注册用户]
MSN多少有问题请教一下
  回复  引用    
#3楼 [楼主]
2006-11-14 11:55 | 刚刚      
@Riancy
你可以加入博客园的QQ群:15338834或博客园的MSN两个群询问:group26801@xiaoi.com和atlas.cnblogs@hotmail.com。我都在其中。
  回复  引用  查看    
2006-11-14 13:13 | Riancy [未注册用户]
在里面叫什么名字啊,我在第三个
  回复  引用    
2006-11-16 11:12 | KiddLee      
我试了一下,但是连接好像有问题,以前没太用过Sql2005
  回复  引用  查看    
2006-11-16 13:03 | KiddLee      
我试了试,报这个错误
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ArgumentException: Keyword not supported: 'provider'.
at System.Data.Common.DbConnectionOptions.ParseInternal(Hashtable parsetable, String connectionString, Boolean buildChain, Hashtable synonyms, Boolean firstKey)
at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Hashtable synonyms, Boolean useOdbcRules)
at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)
at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(String connectionString, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)
at System.Data.SqlClient.SqlConnection.ConnectionString_Set(String value)
at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
at System.Data.SqlClient.SqlConnection..ctor(String connectionString)
at Service.Login() in f:\MyProject\2005\WebSite\WebServiceTest\App_Code\Service.cs:line 72
--- End of inner exception stack trace ---
不知道为什么
  回复  引用  查看    
#7楼 [楼主]
2006-11-18 17:23 | 刚刚      
@KiddLee
请你不要在创建WebService的工程时使用“文件系统”,要使用“Http”。
  回复  引用  查看    
2006-11-20 10:57 | KiddLee      
@刚刚
谢谢,已经是成功了,主要是因为Sql的Service配置不正确
  回复  引用  查看    
#9楼 [楼主]
2006-11-20 11:13 | 刚刚      
@KiddLee
好的。:)
  回复  引用  查看    
2006-11-29 11:05 | yunhuasheng      
好!支持,关注!!
  回复  引用  查看    
2007-02-20 22:02 | JesseZhao      
好东东,持续收藏
  回复  引用  查看    
2007-04-24 15:34 | 蓝狐      
个人认为lz讲的用ADO.NET访问数据库和Web Service似乎没有任何直接联系,因为做普通的.Net应用,也是这样访问数据库,没有什么特别之处。
似乎不应该放到这里来讲!不过LZ的共享精神可嘉!

  回复  引用  查看    
#13楼 [楼主]
2007-04-25 10:25 | 刚刚      
@蓝狐
本来技术就是组合应用的,这里只是说明,在WS中返回断开模式的DS和连接模式的一些其他数据类型。说明的是应用方法的例子,而不是原理!
  回复  引用  查看    
2007-10-30 10:48 | 杰仔      
Server was unable to process request
我也出现这种情况,Web服务就查询表,返回一个字符串..调用几次都正常,如果调用好几次之后,就会出现以上情况,请好心人解决.谢谢...QQ:251827911
  回复  引用  查看    
#15楼 [楼主]
2007-11-05 18:53 | 刚刚      
@杰仔
可能是调用过程有问题,或者连接数过多,要知道操作系统,尤其是WindowsXP是有连接数限制的,当达到顶峰或溢出时就会请求不到了。
  回复  引用  查看    
2008-04-22 17:03 | 冰少爷      
刚同志,帮俺看一下俺的代码有什么问题吗?
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Configuration;
using System.Data.SqlClient;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class UService: System.Web.Services.WebService
{
//private int userRight;
public UService () {

//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}

[WebMethod]
public bool UserValidate(string sUserName,string sPassWord)
{
SqlConnection sconnection = null;
UserInfo uInfo = new UserInfo();

ConnectionStringSettings cs = ConfigurationManager.ConnectionStrings["DB_ESCPV1.0ConnectString"];
string connString = cs.ConnectionString;
sconnection = new SqlConnection(connString);
SqlCommand scommand = new SqlCommand();
scommand.Connection = sconnection;
scommand.CommandText = "select UserName,UserPassword,UserRight " +
"from UserInfo_Table " +
"where UserName = '" + sUserName + "' AND UserPassword = '"
+ sPassWord + "'";
sconnection.Open();
SqlDataReader sdatareader = scommand.ExecuteReader();
if ( sdatareader.Read();)
{
uInfo._userRight = (int)sdatareader.GetInt32(2);

return true;

}
else
{
return false;
}

}
//[WebMethod]
//public int GetUserRightValue()
//{
// return userRight;
//}
}
  回复  引用  查看    
2008-04-22 17:18 | 冰少爷      
uInfo._userRight = (int)sdatareader.GetInt32(2);
//这句调试通不过,这种用法不对吗?
  回复  引用  查看    
#18楼 [楼主]
2008-04-22 20:10 | 刚刚      
@冰少爷
不知道报的错误信息是什么呢?
你似乎想去获得被登录成功者的用户权限,然后给一个类的属性赋值,这个类是uInfo。
其实你完全不必要这么做,不需要在Web Services中定义uInfo类,如果要这个类,这个类也应该在客户端上,而不是在Web Services中(我