首先,我们在SQL Server 2005示例数据库AdventureWorks中创建两个存储过程—GetProducts和UpdateproductPrice。后面,我们将通过SQL Server本机Web服务来访问这两个存储过程。创建它们的相应SQL脚本代码如下所示:


1. USE AdventureWorks
2. 
3. GO
4. 
5. --创建提供给Web服务调用的存储过程
6. 
7. CREATE PROCEDURE Production.GetProducts @Name NVARCHAR(50)=N'%'
8. 
9. AS
10. 
11. SELECT ProductID, [Name], ListPrice
12. 
13. FROM Production.Product
14. 
15. WHERE [Name] LIKE @Name
16. 
17. ORDER BY ProductID
18. 
19. GO
20. 
21. CREATE PROCEDURE Production.UpdateProductPrice
22. 
23.       (
24. 
25.              @productId integer,
26. 
27.              @ListPrice money
28. 
29.       )
30. 
31. AS
32. 
33.       UPDATE Production.Product
34. 
35.       SET ListPrice = @ListPrice
36. 
37.       WHERE ProductID = @productid
38. 
39. GO
40.

很明显,这是两个普通的存储过程,与一般的存储过程创建没有任何不同之处。接下来,让我们重点关注创建设置访问HTTP的位置。

<!--[if !supportLists]-->(二)<!--[endif]-->定义端点—确定SQL Server创建Web服务的位置

Create HTTP End Point是SQL Server 2005为支持本机Web服务访问新增的命令。我们要通过这个命令,指定一个唯一的URL,让SQL Server监听到前端应用程序通过该URL传递的需求,也即前端应用程序以Web服务访问的位置。当底层的http.sys收到对该URL提出的需求时,会自动路由给设置该端点(End Point)的SQL Server实例。

为此,启动SQL Server Management Studio,选择AdventureWorks示例数据库;然后打开一个新的查询窗口并使用如下语句在该数据库中创建HTTP端点:

    1. --创建HTTP端点
    2. 
    3. USE master
    4. 
    5. GO
    6. 
    7. IF EXISTS(SELECT * FROM sys.http_endpoints WHERE name = 'AWProduction')
    8. 
    9. BEGIN
    10. 
    11.       DROP ENDPOINT AWProduction
    12. 
    13. END
    14. 
    15. GO
    16. 
    17. CREATE ENDPOINT AWProduction
    18. 
    19. STATE = STARTED
    20. 
    21. --定义传输协议、监听端口和认证方式
    22. 
    23. AS HTTP(
    24. 
    25. //localhost/AdventureWorks/Production?wsdl” 
    26. 
    27. '/AdventureWorks/Production',
    28. 
    29.       AUTHENTICATION = (INTEGRATED),
    30. 
    31.       PORTS = ( CLEAR ))
    32. 
    33. --存取方法,返回格式…
    34. 
    35. FOR SOAP(
    36. 
    37.    --指定经由Web服务调用存储过程时使用的Web方法名称
    38. 
    39. 'GetProducts' (name='AdventureWorks.Production.GetProducts',FORMAT=ROWSETS_ONLY),
    40. 
    41. 'UpdateProductPrice' (name='AdventureWorks.Production.UpdateProductPrice'
    42. 
    43.       BATCHES = ENABLED,
    44. 
    45.       WSDL = DEFAULT,
    46. 
    47. 'AdventureWorks',
    48. 
    49. 'http://AdventureWorks/'
    50. 
    51. )
    52. 
    53.


    在此,第一个Web方法返回执行存储过程后所得的查询结果,内容是ROWSET结构,因此我们定义FORMAT参数类型为ROWSETS_ONLY。注意,我们还设置BATCHES=ENABLED,从而允许Web服务提供直接执行T-SQL默认的sqlbatchWeb方法。

    运行上面的脚本。一切正常的话,则在“对象资源管理器”的“服务器对象”下出现新创建的SOAP端点(名字为AWProduction)。

    <!--[if !supportLists]-->(三)<!--[endif]-->设置Windows帐号以便通过Web服务访问SQL Server

    既然已经成功创建HTTP端点,接下来,我们必须保证所用的Windows帐户能够安全地通过Web服务访问SQL Server。因为经由系统监听器http.sys来实现认证,所以我们仅能使用Windows帐户而无法通过普通的SQL Server帐户进行访问。为此,我们通过下面三步来创建可用帐户:

    允许用Windows帐户访问SQL Server以及对前面创建的Web方法所对应的SQL对象要使用的数据库;

    赋予此用户可以执行Web方法所对应的存储过程或用户自定义函数;

    允许该用户连接到我们所设置的端点。

    下面的代码展示了的通过T-SQL脚本赋予特定Windows帐户通过Web服务访问SQL Server内对象的实现思路:


    1. --设置某帐户能否访问HTTP端点或调用Web方法
    2. 
    3. --为此,你需要创建一个Windows账户—Tom
    4. 
    5. --【注意】只有通过Master系统数据库才能设置端点的CONNECT联机访问能力
    6. 
    7. USE Master
    8. 
    9. GO
    10. 
    11. --使当前Windows账户能够登录到SQL Server
    12. 
    13. CREATE LOGIN [ZXZ2003/Tom] FROM WINDOWS
    14. 
    15. WITH DEFAULT_DATABASE = AdventureWorks
    16. 
    17. --允许经由Web Service的端点(End Point)访问SQL Server
    18. 
    19. GRANT CONNECT ON ENDPOINT:: AWProduction TO [ZXZ2003/Tom]
    20. 
    21. GO
    22. 
    23. USE AdventureWorks
    24. 
    25. GO
    26. 
    27. --允许登录的SQL Server帐户访问当前数据库
    28. 
    29. CREATE USER [ZXZ2003/Tom] For LOGIN [ZXZ2003/Tom]
    30. 
    31. --让该帐户执行与前面Web方法相关联的存储过程
    32. 
    33. GRANT EXECUTE ON Production.GetProducts TO [ZXZ2003/Tom]
    34. 
    35. GRANT EXECUTE ON Production.UpdateProductPrice TO [ZXZ2003/Tom]
    36. 
    37. --完成测试后,删除前面“允许”的Windows帐户
    38. 
    39. DROP USER [ZXZ2003/Tom]
    40. 
    41. DROP LOGIN [ZXZ2003/Tom]
    42.


    注意,在上面脚本中,我们首先创建一个名为Tom的Windows帐户(完整形式为“ZXZ2003/Tom”)。然后,使用CREATE LOGIN允许该帐户登录到SQL Server。接下来,使用GRANT CONNECT允许此帐户使用前面创建的Web服务的HTTP端点访问SQL Server。最后,授予此账户EXECUTE权限,从而允许他执行与前面Web方法相关联的存储过程。

    <!--[if !supportLists]-->二、       <!--[endif]-->创建前端应用程序

    现在,我们通过Visual Studio 2005创建一个Windows桌面应用程序来验证通过调用前面创建的Web服务达到访问SQL Server 2005的目的。大致步骤如下:

    <!--[if !supportLists]-->1.      <!--[endif]-->启动VS2005,选择C#创建一个Windows应用程序,命名为“WebServiceTestClient”; 
          
    <!--[if !supportLists]-->2.      <!--[endif]-->通过“添加Web参考”引用WSDL创建Web服务的代理程序类; 
          
    <!--[if !supportLists]-->3.      <!--[endif]-->声明代理程序类的变量并赋予该类的实例; 
          
    <!--[if !supportLists]-->4.      <!--[endif]-->设置访问Web服务的账号身份; 
          
    <!--[if !supportLists]-->5.      <!--[endif]-->通过代理程序实例调用Web方法; 
          
    <!--[if !supportLists]-->6.      <!--[endif]-->处理Web方法返回的结果。

    表单布局如下图2所示:


    图2.SQL Server 2005本机Web服务前端测试程序界面。

    表单中间的DataGridView控件用于显示和编辑产品记录信息。

    要在程序中引用Web服务,只需右击项目ClientTest并选择“添加Web引用…”以此指定相应的URI为:

    http://localhost/AdventureWorks/Production?WSDL

    之后,系统自动为该Web服务创建相应的代理对象。

    为代理类声明一个变量并进行下面的赋值:



    privatesql_endpoint.AWProduction prxy =newsql_endpoint.AWProduction();

    在本示例中,我们将测试不同的Windows登录账户是否有权利通过Web服务访问SQL Server,并执行相应的Web服务以查询或修改数据表内的记录。

    首先,我们声明必要的私有变量—productsDS和prxy。然后,在表单构造器中允许此代理使用缺省的Windows登录账户通过Web服务访问SQL Server:

     


    1. //用于存放从服务器端取回数据集的DataSet 
    2. 
    3.              privateDataSet productsDS;
    4. 
    5. //声明并且初始化一个Web服务代理的实例 
    6. 
    7.              privatesql_endpoint.AWProduction prxy =newsql_endpoint.AWProduction();
    8. 
    9.              publicForm1(){
    
    10. 
    11.                     InitializeComponent();
    12. 
    13. //经由缺省的Windows集成认证方式调用Web方法 
    14. 
    15.                     prxy.Credentials = .CredentialCache.DefaultCredentials;
    16. 
    17.              }
    18.

    接下来,我们要设置在上图中用户修改登录Web服务的账号时通过程序代码来赋予代理程序所使用的账号:

     




    1. privatevoidradioButton1_CheckedChanged(objectsender,EventArgse) {
    
    2. 
    3. //改变调用Web方法的认证身份 
    4. 
    5.                     SetCredential();
    6. 
    7.              }
    8. 
    9.              privatevoidSetCredential(){
    
    10. 
    11. //建立凭证以登录到Web服务 
    12. 
    13. if(radioButton1.Checked)
    14. 
    15. //集成式认证 
    16. 
    17.                            prxy.Credentials = .CredentialCache.DefaultCredentials;
    18. 
    19. else{
    
    20. 
    21. if(txtAccount.Text ==""|| txtPassword.Text ==""){
    
    22. 
    23. "在自定义账号密码登录时,账号或密码不能为空!");
    24. 
    25. true;
    26. 
    27. return;
    28. 
    29.                            }
    30. 
    31. else{
    
    32. 
    33. //由用户自己来输入一个帐户口令 
    34. 
    35.                                   prxy.Credentials =new.NetworkCredential(txtAccount.Text, txtPassword.Text);
    36. 
    37.                            }
    38. 
    39.                     }
    40. 
    41.              }
    42.


    至此,由于我们已经建立了访问Web服务的适当身份,然后,我们就可以开始使用前面定义的Web服务访问记录;最终返回的结果将显示于表单中的DataGridView控件内。下面是相应的代码片断:

     


    1. privatevoidgetProductsButton_Click(objectsender,EventArgse) {
    
    2. 
    3.                            DisplayProducts();
    4. 
    5.              }
    6. 
    7.              privatevoidDisplayProducts(){
    
    8. 
    9. //取数据 
    10. 
    11. try{
    
    12. 
    13. //调用GetProducts Web方法 
    14. 
    15. //取DataSet实例 
    16. 
    17.