在银光中国网(SilverlightChina.Net)有一篇"Silverlight与常用数据库互操作系列"文章,其中介绍了使用Silverlight存取不同数据库的方法和步骤。但是对于Silverlight存取MS SQL介绍的不够全面,这里我想介绍Silverlight如何通过WCF访问MSSQL数据库存储过程的。希望对大家能够有所帮助。
我们要实现, 用户输入用户名和密码后,点击登录按钮,传递用户名和密码到服务器端, 通过WCF访问MSSQL数据库,调用存储过程,在服务器端对用户名和密码进行匹配,匹配成功,则返回登录成功,否则,则是失败。
在文章开始前,我们需要做一下准备工作,
- 开发环境需求: VS2008 SP1, Silverlight 3 Develop Tools for VS2008 SP1, 客户端Silverlight 3 Runtime, MSSQL 2005 SP3 ;
- 建立例程数据库 SilverlightDemo,在数据库中建立一个新表 Users,包含以下字段;
添加内容到Users表,为了方便起见,密码全部使用明文,在正式项目中,建议对密码字段进行加密使用。
这里,我们验证用户名和密码,有两种简单方式,
一是使用存储过程读取用户名和密码,然后在服务器端进行用户名和密码匹配校验,如果查找到匹配数据,则返回登录成功,否则,则是登录失败;
二是传用户名和密码到存储过程中,在数据库存储过程中进行判断,使用Select语句进行查找,对应用户名和密码,如果查找到匹配结果,则返回用户ID,服务器端接收到用户ID,则返回登录成功,否则,则是失败;
在本例中,主要是对Silverlight访问数据库进行讲述,所以,对于验证方法,不进行详细描述和讲解,如果有问题,可以留言给我,我们继续讨论,这里,我将使用第一种验证方法。 为此,建立一个简单的存储过程:
2(@UserNameVarchar(30))
3AS
4
5SelectcUserName,cPassword
6FromUsers
7WherecUserName=@UserName
8
9RETURN
10
11SETNOCOUNTON
在完成上面的准备工作后,开始建立新的Silverlight项目,
1. 建立一个新项目"SilverlightDBDemo",
2. 在MainPage中建立简单的登录界面,如下:
3. 在Web项目中添加新选项
4.添加一个简单的用户信息类Users,作为WCF的契约成员,当我们从数据库中读取信息后,将赋值给该类的契约成员,方便客户端进行调用;
VS2008将自动生成Users类代码,在类命名前添加数据契约属性[DataContract()]。 为了能够使绑定数据返回修改通知,这里需要继承INotifyPropertyChanged接口,该步骤不添加对本教程也没有影响,为了以后例程代码完整性,这里我继承了该接口。在接口上点击右键,生成代码。
代码如下:
2{
3[DataContract()]
4publicclassUsers:INotifyPropertyChanged
5{
6
7#regionINotifyPropertyChangedMembers
8
9publiceventPropertyChangedEventHandlerPropertyChanged;
10
11#endregion
12}
13}
14
5. 在Users类中,添加契约成员
2[DataMember()]
3publicstringUserName
4{
5get{returnuserName;}
6set{userName=value;}
7}
8
9privatestringpassword;
10[DataMember()]
11publicstringPassword
12{
13get{returnpassword;}
14set{password=value;}
15}
6. 建立构造函数 public Users(string sUserName,string sPassword),传递用户名和密码给契约成员;
2usingSystem.ComponentModel;
3usingSystem.Runtime.Serialization;
4
5namespaceSilverlightDBDemo.Web
6{
7[DataContract()]
8publicclassUsers:INotifyPropertyChanged
9{
10privatestringuserName;
11[DataMember()]
12publicstringUserName
13{
14get{returnuserName;}
15set{userName=value;}
16}
17
18privatestringpassword;
19[DataMember()]
20publicstringPassword
21{
22get{returnpassword;}
23set{password=value;}
24}
25
26publicUsers(stringsUserName,stringsPassword)
27{
28UserName=sUserName;
29Password=sPassword;
30}
31
32#regionINotifyPropertyChangedMembers
33
34publiceventPropertyChangedEventHandlerPropertyChanged;
35
36#endregion
37}
38}
7. 添加"Silverlight-enabled WCF Service",修改服务名字为 DBService.svc,需要注意的是,WCF service对于Silverlight仅支持BasicHttpBinding,而VS2008自动生成是customBinding,很多朋友说使用了"Silverlight-enabled WCF Service",链接数据库仍旧失败,无法找到远程服务器,是因为没有使用BasicHttpBinding进行通讯,造成的失败。
后文我将讲述如何修改。
8. 添加后,在Web服务器端会有DBService.svc和DBService.svc.cs文件出现,VS2008将自动更新Web项目的类库引用;
9. 双击进入DBService.svc.cs文件,可以看到以下代码:
2usingSystem.Linq;
3usingSystem.Runtime.Serialization;
4usingSystem.ServiceModel;
5usingSystem.ServiceModel.Activation;
6usingSystem.Collections.Generic;
7usingSystem.Text;
8
9namespaceSilverlightDBDemo.Web
10{
11[ServiceContract(Namespace="")]
12[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
13publicclassDBService
14{
15[OperationContract]
16publicvoidDoWork()
17{
18//Addyouroperationimplementationhere
19return;
20}
21
22//Addmoreoperationshereandmarkthemwith[OperationContract]
23}
24}
这里我们没有修改ServiceContract命名空间,所以保持默认为空,AspNet的兼容需求模式我们保持默认。在正式项目中,我们习惯将所有的[OperationContract]函数放入一个接口文件中,这样方便扩展以及维护,在本例,为了方便大家理解,就不把[OperationContract]放入接口文件。 在VS2008自动生成代码下面直接添加数据库访问代码。
10. 在添加服务器端数据库访问代码前,需要修改Web.Config文件。和Asp.Net项目一样,在链接数据库前,我们首先需要在Web.Config中配置数据库连接字符串,请自行替换数据库登录ID和密码
2<addkey="DbServiceConnectionString"value="DataSource=(Local);InitialCatalog=SilverlightDemo;UserId=dev;Password=dev;"/>
3</appSettings>
11. 前文已经说过,Silverlight仅支持使用BasicHttpBinding通过WCF service进行通讯,而VS2008自动生成的代码是customBinding,所以,我们也需要在Web.Config中进行修改.下面是VS2008自动生成的Web.Config部分代码,划线部分是下面要修改的部分。
2<behaviors>
3<serviceBehaviors>
4<behaviorname="SilverlightDBDemo.Web.DBServiceBehavior">
5<serviceMetadatahttpGetEnabled="true"/>
6<serviceDebugincludeExceptionDetailInFaults="False"/>
7</behavior>
8</serviceBehaviors>
9</behaviors>
10<bindings>
11<customBinding>
12<bindingname="customBinding0">
13<binaryMessageEncoding/>
14<httpTransport/>
15</binding>
16</customBinding>
17</bindings>
18<serviceHostingEnvironmentaspNetCompatibilityEnabled="true"/>
19<services>
20<servicebehaviorConfiguration="SilverlightDBDemo.Web.DBServiceBehavior"
21name="SilverlightDBDemo.Web.DBService">
22<endpointaddress=""binding="customBinding"bindingConfiguration="customBinding0"
23contract="SilverlightDBDemo.Web.DBService"/>
24<endpointaddress="mex"binding="mexHttpBinding"contract="IMetadataExchange"/>
25</service>
26</services>
27</system.serviceModel>
这里我们需要修改以下几个地方:
首先删除customBinding,从上面代码,第10行,到17行,使用下面代码替换:
2<basicHttpBinding>
3<bindingname="BasicHttpBinding_IDataService"
4maxBufferPoolSize="2147483647"
5maxReceivedMessageSize="2147483647"
6maxBufferSize="2147483647">
7<readerQuotas
8maxArrayLength="2147483647"
9maxBytesPerRead="2147483647"
10maxDepth="2147483647"
11maxNameTableCharCount="2147483647"
12maxStringContentLength="2147483647"/>
13</binding>
14</basicHttpBinding>
15</bindings>
其中那些2147483647之类的属性可以删除,但是如果读取数据库中的大型表格,就需要设置缓冲池之类的尺寸了。这里,我们已经使用了basicHttpBinding. Binding name我使用了BasicHttpBinding_DBService,大家可以随意更换,下面将用到。
然后修改22行和23行的代码,将endpoint中的binding,内容修改为basicHttpBinding,bindingConfiguration的内容修改为BasicHttpBinding_DBService。
2contract="SilverlightDBDemo.Web.DBService"/>
12. 现在我们可以在DBService.svc.cs中添加存取数据库代码,对用户名和密码进行简单匹配,这里不再着重讲述如何条件匹配登录信息。这里演示了如何调用数据库存储过程。完成存取数据库代码后,成功编译Web项目。代码有点长,这里折叠起来。
2
3[OperationContract]
4publicboolGetUser(stringcUserName,stringcPassword)
5{
6SqlConnectionconn=newSqlConnection(connectionString);
7SqlCommandcmd=newSqlCommand("Login",conn);
8cmd.CommandType=CommandType.StoredProcedure;
9cmd.Parameters.AddWithValue("@UserName",cUserName);
10
11try
12{
13conn.Open();
14SqlDataReaderreader=cmd.ExecuteReader(CommandBehavior.SingleRow);
15if(reader.Read())
16{
17Usersuser=newUsers((string)reader["cUserName"],
18(string)reader["cPassword"]);
19if(user.Password==cPassword)
20{
21returntrue;
22}
23else
24{
25returnfalse;
26}
27}
28else
29{
30returnfalse;
31}
32}
33finally
34{
35conn.Close();
36}
37}
13. 在SilverlightDBDemo客户端,点击右键添加服务引用
14. 在弹出窗口中,点击"Discover",查找本地WCF service。在地址栏会自动搜索到本地的Service引用,在Services树形框中我们可以看到,在服务器端建立的DBService.svc,双击打开,可以看到,我们建立的GetUser函数,以及默认的DoWork函数。修改下面的命名空间为"DBService",方便调用。
15. 点击"Advanced.."高级按钮,确认选中"Reuse types in referenced assembiles",如下图,
16. 然后,点击确定,会在客户端中生成DBService服务引用。
17. 在生成DBService服务引用后,VS2008会自动生成一个ServiceReferences.ClientConfig文件。
我们需要留意查看一下该文件内容。其中,bindings信息是basicHttpBinding,而endpoint内容和Web.Config中的内容相同。这里我们不需要修改任何代码。
2<system.serviceModel>
3<bindings>
4<basicHttpBinding>
5<bindingname="BasicHttpBinding_DBService"maxBufferSize="2147483647"
6maxReceivedMessageSize="2147483647">
7<securitymode="None">
8<transport>
9<extendedProtectionPolicypolicyEnforcement="Never"/>
10</transport>
11</security>
12</binding>
13</basicHttpBinding>
14</bindings>
15<client>
16<endpointaddress="http://localhost/SilverlightDBDemo.Web/DBService.svc"
17binding="basicHttpBinding"bindingConfiguration="BasicHttpBinding_DBService"
18contract="DBService.DBService"name="BasicHttpBinding_DBService"/>
19</client>
20</system.serviceModel>
21</configuration>
22
18. 下面我们将在客户端调用该服务引用,获取数据库的返回值,根据返回值,我们将简单判断登录是否成功。
进入MainPage.xaml.cs中,建立GetUser方法。该代码中EndpointAddress是最重要的,出现没有发现远程服务器错误,和这里设置也有关系。在client_GetUserCompleted中,e.Result代表了数据库返回值。可以接受任何值,大家可以根据需要进行值类型转换。每次,用户点击登陆按钮,Silverlight客户端都会向服务器端请求验证,返回结果会在提示信息栏显示。
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
2{
3EndpointAddressaddress=newEndpointAddress(newUri(Application.Current.Host.Source,"/SilverlightDBDemo.Web/DBService.svc"));
4DBServiceClientclient=newDBServiceClient(newBasicHttpBinding(),address);
5client.GetUserCompleted+=client_GetUserCompleted;
6client.GetUserAsync(txtUsername.Text,pbPassword.Password);
7}
8
9privatevoidclient_GetUserCompleted(objectsender,GetUserCompletedEventArgse)
10{
11try
12{
13if(e.Result)
14{
15tbMessage.Text="登录成功!";
16}
17else
18{
19tbMessage.Text="登录失败!";
20}
21}
22catch(Exceptionerror)
23{
24tbMessage.Text=error.ToString();
25}
26}
27
28privatevoidbtLogin_Click(objectsender,RoutedEventArgse)
29{
30GetUser();
31}
登录成功如下图:
到这里为止,我想你已经学会了如何使用WCF存取MSSQL数据库了。如果有问题,可以留言给我,或者到Silverlight开发100844510来讨论。
本文为原创文章,第一次发布在 银光中国网(SilverlightChina.Net)
如需转载,请注明出处,谢谢