在VS.NET中创建一个名称为PCSWebSrv2的新Web服务项目。首先,在global.asax的Application_Start()处理程序中给项目添加一些代码。把PCSWebApp3.mdb中的所有数据都载入到数据集中并且保存数据集,其中涉及的大部分代码前面已讨论过,因为前面已经把数据库载入到DataSet中。实际上,可以从第25章的PCSWebApp3的WebForm1.aspx.cs中复制需要的所有代码,其中包括InitializeComponent()中的数据库连接字符串(因为您使用的连接字符串有可能不相同,所以这里就不显示了)—— 只有几处需要修改:
protected void Application_Start(Object sender, EventArgs e)
{
System.Data.DataSet ds;
System.Data.OleDb.OleDbConnection oleDbConnection1;
System.Data.OleDb.OleDbDataAdapter daAttendees;
System.Data.OleDb.OleDbDataAdapter daRooms;
System.Data.OleDb.OleDbDataAdapter daEvents;
oleDbConnection1 = new System.Data.OleDb.OleDbConnection();
oleDbConnection1.ConnectionString = @" ... ";
oleDbConnection1.Open();
ds = new DataSet();
daAttendees = new System.Data.OleDb.OleDbDataAdapter(
"SELECT * FROM Attendees", oleDbConnection1);
daRooms = new System.Data.OleDb.OleDbDataAdapter(
"SELECT * FROM Rooms", oleDbConnection1);
daEvents = new System.Data.OleDb.OleDbDataAdapter(
"SELECT * FROM Events", oleDbConnection1);
daAttendees.Fill(ds, "Attendees");
daRooms.Fill(ds, "Rooms");
daEvents.Fill(ds, "Events");
oleDbConnection1.Close();
Application["ds"] = ds;
}
这里需要注意代码中的最后一行。通常,Application(以及Session)对象都有一个名/值对的集合,可以在该集合中保存数据。这里在Application存储中创建一个名称ds,它从数据库中提取数据集ds的串行化值,其中包含表Attendees、Rooms和Events。这样,Web服务对象的所有实例在任何时间都可以访问ds中保存的值。
为了能使上面的代码正常执行,也需要给global.asax.cs添加一个对System.data命名空间的引用:
...
using System.Data;
这项技术非常适合于只读数据,因为多个线程可以访问它,减少了对数据库中数据的载入。但要注意,由于Events表有可能发生变化,在Events表发生变化时,必须更新应用程序层DataSet。稍后会介绍这一内容。
接下来需要把方法GetData()添加给Service1.asmx.cs中的服务:
[WebMethod]
public DataSet GetData()
{
return (DataSet) Application["ds"];
}
ds = (DataSet)Application["ds"];
ds.Tables["Events"].Clear();
daEvents.Fill(ds, "Events");
Application.Lock();
Application["ds"] = ds;
Application.UnLock();
oleDbConnection1.Close();
}
}
最后,返回queryResult,以便让客户知道查询是否成功:
[WebMethod]
public int AddEvent(String eventName, String eventRoom,
String eventAttendees, String eventDate)
{
...
return queryResult;
}
至此,就完成了Web服务的所有工作,如同以前,可以对Web服务进行测试,测试的方法就是把Web浏览器指向.asmx文件,这样,不用编写任何客户机代码,就可以添加记录,查看由GetData()返回的DataSet的XML表示。
在继续之前,需要讨论DataSet对象和Web服务的组合使用。初看起来这似乎是交换数据的一种荒谬方式,而实际上这是一种极其有用的技术。
DataSet类的用途非常广泛,如果查看为GetData()方法生成的WSDL,就会看到如下内容:
<s:element FTEL="GetDataResponse">
<s:complexType />
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" FTEL="GetDataResult">
<s:complexType>
<s:sequence>
<s:element ref=”s:schema” />
<s:any />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
可以看出,这是非常一般的代码,允许传送进来的DataSet对象包含用内联模式指定的任何数据。但是,这表示WSDL没有完整地描述Web服务。对于.NET客户这不是个问题,在前面的示例中传送简单的字符串时,一切都很正常,惟一的区别是我们交换了一个DataSet对象。但是,非.NET客户必须提前了解要传送的数据,或者某个等价的DataSet类,才能访问数据。
这个问题的解决方法是把数据重新封装为另一种格式,例如结构数组。但是,这里使用DataSet对象不会出问题,而且还可以大大简化其他代码。
上面代码使用与Application_Load()相同的语法来访问dataset,这样,就可以简单地将数据转换为正确的类型,并返回。
AddEvent()方法稍微有点复杂,从概念上讲,需要做下面的事情:
● 接受来自客户的事件数据。
● 使用那些数据创建SQL INSERT语句。
● 连接数据库并且执行SQL语句。
● 如果添加成功,就需要刷新Application[“ds”]中的数据。
● 把成功或失败的通知返回给客户(如果有必要,允许客户刷新他们的DataSet)。
从现在开始,把所有的字段作为字符串来接受:
[WebMethod]
public int AddEvent(String eventName, String eventRoom,
String eventAttendees, String eventDate)
{
}
下面声明访问数据库、连接数据库以及执行查询时需要的对象,完成这些工作所使用的代码与PCSWebApp3中的代码相似(此外,这里也需要连接字符串,但是并没有给出):
[WebMethod]
public int AddEvent(String eventName, String eventRoom,
String eventAttendees, String eventDate)
{
System.Data.OleDb.OleDbConnection oleDbConnection1;
System.Data.OleDb.OleDbDataAdapter daEvents;
DataSet ds;
oleDbConnection1 = new System.Data.OleDb.OleDbConnection();
oleDbConnection1.ConnectionString = @" ... ";
String oleDbCommand = "INSERT INTO Events (Name, Room, AttendeeList," + " EventDate) VALUES ('" + eventName + "', '" + eventRoom + "', '" + eventAttendees + "', '" + eventDate + "')";
System.Data.OleDb.OleDbCommand insertCommand =
new System.Data.OleDb.OleDbCommand(oleDbCommand,
oleDbConnection1);
oleDbConnection1.Open();
int queryResult = insertCommand.ExecuteNonQuery();
}