1.前言
上一篇,我們通過VS自帶的模板引擎自動生成了一個wcf程序,接下來我們將手動實現一個wcf程序。由於應用程序開發中一般都會涉及到大量的增刪改查業務,所以這個程序將簡單演示如何在wcf中構建簡單的增刪改查服務。我們知道WCF是一組通訊服務框架,我將解決方案按大范圍划分為服務端,客戶端通過服務寄宿程序產生的代理來調用服務端的公開給客戶端消費的方法。總個解決方案由五個項目工程:
- Service:定義服務契約接口和實現服務契約,此項目類型為類庫項目
- Common:通用層定義數據訪問的幫助類,此項目類型為類庫項目
- Entity:定義數據契約,也就是實體對象,此項目類型為類庫項目
- Host:服務寄宿程序,將Service服務程序寄宿在該程序中,此項目類型為控制台應用程序
- Client:客戶端程序,實現對服務的消費,此項目類型為web項目
2.實現程序
步驟一:建立數據庫
為方便演示操作,我們建立一個簡單的表,學生信息(Student),創建的腳本如下(此處我采用的是sql server數據庫):
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIERON GO CREATE TABLE[dbo].[Student]( [ID] [int] NOT NULL, [Name] [nvarchar](50) NULL, [Age] [int] NULL, [Grade] [nvarchar](50) NULL, [Address] [nvarchar](50) NULL, CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
步驟二:建立Common層
新建一個空白解決方案,名稱為WcfDemo,創建完成后新增一個類庫文件命名為Common,再添加一個數據庫訪問幫助類DbHelperSQL:代碼如下:
using System; using System.Collections; using System.Collections.Specialized; using System.Data; using System.Data.SqlClient; using System.Configuration; using System.Data.Common; using System.Collections.Generic; namespace Common { public class DbHelperSQL { public static string connectionString ="server=.;database=test;uid=sa;pwd=sa123"; public static int ExecuteSql(stringSQLString) { using (SqlConnection connection =new SqlConnection(connectionString)) { using (SqlCommand cmd = newSqlCommand(SQLString, connection)) { try { connection.Open(); int rows =cmd.ExecuteNonQuery(); return rows; } catch(System.Data.SqlClient.SqlException e) { connection.Close(); throw e; } } } } public static SqlDataReaderExecuteReader(string strSQL) { SqlConnection connection = newSqlConnection(connectionString); SqlCommand cmd = newSqlCommand(strSQL, connection); try { connection.Open(); SqlDataReader myReader =cmd.ExecuteReader(CommandBehavior.CloseConnection); return myReader; } catch(System.Data.SqlClient.SqlException e) { throw e; } } public static DataSet Query(stringSQLString) { using (SqlConnection connection =new SqlConnection(connectionString)) { DataSet ds = new DataSet(); try { connection.Open(); SqlDataAdapter command =new SqlDataAdapter(SQLString, connection); command.Fill(ds,"ds"); } catch(System.Data.SqlClient.SqlException ex) { throw newException(ex.Message); } return ds; } } } }
步驟三:建立Entity層
在WcfDemo解決方案上新建一個名稱為Entity的類庫項目,添加對System.Runtime.Serialization的引用,創建服務的數據契約。新增Student類,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; namespace Entity { [DataContract] public class Student { [DataMember] public int ID { get; set; } [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } [DataMember] public string Grade { get; set; } [DataMember] public string Address { get; set; } } }
步驟四:建立Service層
此項目需要對Common和Entity的引用,再添加對System.ServiceModel的引用,以創建服務契約。在該項目中添加IStudent接口,定義服務契約接口,代碼如下:
using System.Collections.Generic; using System.ServiceModel; using Entity; namespace Service { [ServiceContract] public interface IStudent { [OperationContract] List<Student> GetInfo(stringstrWhere); [OperationContract] bool Add(Student model); [OperationContract] bool Update(Student model); [OperationContract] bool Delete(int id); [OperationContract] bool Exist(int id); } }
再添加EFStudent類,實現對IStudent接口的實現,代碼如下:
using System; using System.Collections.Generic; using System.Text; using System.Data; using Common; using Entity; namespace Service { public class EFStudent:IStudent { public List<Student>GetInfo(string strWhere) { List<Student> listData = newList<Student>(); string strSql = "select * fromstudent"; DataTable dt=DbHelperSQL.Query(strSql).Tables[0]; if (null != dt &&dt.Rows.Count > 0) { for (int i = 0; i <dt.Rows.Count; i++) { Student model = newStudent(); model.ID =Convert.ToInt32(dt.Rows[i]["ID"]); model.Name =dt.Rows[i]["Name"].ToString(); model.Age =Convert.ToInt32(dt.Rows[i]["Age"]); model.Grade =dt.Rows[i]["Grade"].ToString(); model.Address =dt.Rows[i]["Address"].ToString(); listData.Add(model); } } return listData; } public bool Add(Student model) { StringBuilder strSql = newStringBuilder(); strSql.Append(" insert intostudent values "); strSql.Append(" ( "); strSql.Append(" " +model.ID + ", "); strSql.Append(" '" +model.Name + "', "); strSql.Append(" " +model.Age + ", "); strSql.Append(" '" +model.Grade + "', "); strSql.Append(" '" +model.Address + "' "); strSql.Append(" ) "); int rows =DbHelperSQL.ExecuteSql(strSql.ToString()); if (rows > 0) { return true; } else { return false; } } public bool Update(Student model) { StringBuilder strSql = newStringBuilder(); strSql.Append(" update studentset "); strSql.Append(" Name= '"+ model.Name + "', "); strSql.Append(" Age= " +model.Age + ", "); strSql.Append(" Grade= '" +model.Grade + "', "); strSql.Append(" Address='" + model.Address + "' "); strSql.Append(" WhereID=" + model.ID + " "); int rows =DbHelperSQL.ExecuteSql(strSql.ToString()); if (rows > 0) { return true; } else { return false; } } public bool Delete(int id) { StringBuilder strSql = new StringBuilder(); strSql.Append(" delete fromstudent where ID=" + id + " "); int rows =DbHelperSQL.ExecuteSql(strSql.ToString()); if (rows > 0) { return true; } else { return false; } } public bool Exist(int id) { StringBuilder strSql = newStringBuilder(); strSql.Append(" select ID fromstudent where ID=" + id + " "); DataTable dt =DbHelperSQL.Query(strSql.ToString()).Tables[0]; if (null != dt &&dt.Rows.Count > 0) { return true; } else { return false; } } } }
步驟五:建立Host層,對Service進行寄宿
此項目需要對Service項目的引用,並添加對using System.ServiceModel的引用,添加寄宿的服務配置文件App.config,代碼如下:
<?xmlversion="1.0"?> <configuration> <system.serviceModel> <services> <servicename="Service.EFStudent"behaviorConfiguration="EFStudentBehavior"> <host> <baseAddresses> <addbaseAddress="http://127.0.0.1:1234/EFStudent/"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding"contract="Service.IStudent"/> <endpoint address="mex"binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behaviorname="EFStudentBehavior"> <serviceMetadatahttpGetEnabled="True"/> <serviceDebugincludeExceptionDetailInFaults="True"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> <startup> <supportedRuntime version="v4.0"sku=".NETFramework,Version=v4.0"/> </startup> </configuration>
服務寄宿程序Host的Program.cs的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using Service; namespace Host { class Program { static void Main(string[] args) { try { using (ServiceHost host = newServiceHost(typeof(EFStudent))) { host.Opened += delegate { Console.WriteLine("StudentService已經啟動,按任意鍵終止!"); }; host.Open(); Console.Read(); } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadLine(); } } } }
此時,可以編譯程序,找到Host項目生成目錄,運行Host.exe,就可以對服務進行寄宿,如果寄宿成功,在瀏覽器中輸入http://127.0.0.1:1234/EFStudent地址,就可以看到如下圖所示頁面:
步驟六:建立Web客戶端
新建一個空Client的Web引用程序,添加對服務的引用,輸入剛才在瀏覽器中輸入的地址,然后點擊發現前往按鈕就可以發現服務了,點擊確定添加對服務的引用,vs會自動生成對服務的應用配置文件和代理類,如果需要手動生成,可以參考WCF初探—1:認識wcf。添加MainForm.aspx頁面,前端代碼如下:
<%@ PageLanguage="C#" AutoEventWireup="true"CodeBehind="MainForm.aspx.cs"EnableEventValidation="false" Inherits="Client.MainForm" %> <!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <headrunat="server"> <title></title> <scripttype="text/javascript"> var prevselitem = null; function selectx(row) { if (prevselitem != null) { prevselitem.style.backgroundColor = '#ffffff'; } row.style.backgroundColor ='PeachPuff'; prevselitem = row; } </script> </head> <body> <form id="form1"runat="server"> <asp:GridView ID="GridView1"runat="server" AutoGenerateColumns="False" onrowdeleting="GridView1_RowDeleting" onrowdatabound="GridView1_RowDataBound" onrowcommand="GridView1_RowCommand"> <Columns> <asp:TemplateFieldHeaderText="編號"> <ItemTemplate> <asp:LabelID="lbl_id" runat="server" Text='<%#Bind("ID") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> <asp:BoundFieldDataField="Name" HeaderText="姓名" /> <asp:BoundField DataField="Age"HeaderText="年齡"/> <asp:BoundFieldDataField="Grade" HeaderText="年級" /> <asp:BoundFieldDataField="Address" HeaderText="家庭地址" /> <asp:CommandFieldHeaderText="刪除"ShowDeleteButton="True" /> <asp:TemplateFieldHeaderText="編輯"> <ItemTemplate> <asp:LinkButtonID="lbtID" CommandName="lbtn" runat="server"ForeColor="Blue" Text="編輯"> </asp:LinkButton> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> <p>編號<asp:TextBox ID="txt_id"runat="server"></asp:TextBox></p> <p>姓名<asp:TextBox ID="txt_name"runat="server"></asp:TextBox></p> <p>年齡<asp:TextBox ID="txt_age"runat="server"></asp:TextBox></p> <p>年級<asp:TextBox ID="txt_grade"runat="server"></asp:TextBox></p> <p>家庭地址<asp:TextBox ID="txt_address"runat="server"></asp:TextBox></p> <asp:Button ID="btnAdd"runat="server" Text="保存" onclick="btnAdd_Click" /> </form> </body> </html>
后台代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using Client.ServiceReference; namespace Client { public partial class MainForm :System.Web.UI.Page { StudentClient proxy = newStudentClient(); protected void Page_Load(object sender,EventArgs e) { if (!Page.IsPostBack) { BindData(); } } private void BindData() { Student[] listData =proxy.GetInfo(""); this.GridView1.DataSource =listData.ToList(); this.GridView1.DataBind(); } protected void btnAdd_Click(objectsender, EventArgs e) { Student model = new Student(); model.ID =Convert.ToInt32(this.txt_id.Text); model.Name = this.txt_name.Text; model.Age =Convert.ToInt32(this.txt_age.Text); model.Grade = this.txt_grade.Text; model.Address =this.txt_address.Text; if (proxy.Exist(model.ID)) { proxy.Update(model); } else { proxy.Add(model); } BindData(); } protected voidGridView1_RowDeleting(object sender, GridViewDeleteEventArgs e) { int id =Convert.ToInt16(((GridView1.Rows[e.RowIndex].FindControl("lbl_id") asLabel).Text)); bool flag = proxy.Delete(id); if (flag) { Response.Write("<Script>alert(' 刪除成功!')</Script> "); BindData(); } else { Response.Write("<Script>alert(' 刪除失敗!')</Script> "); } } protected voidGridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType ==DataControlRowType.DataRow) { e.Row.Attributes.Add("onclick", e.Row.ClientID.ToString() +".checked=true;selectx(this)");//點擊行變色 } } protected voidGridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName =="lbtn") { GridViewRow gvrow =(GridViewRow)(((LinkButton)e.CommandSource).NamingContainer); //獲取被點擊的linkButton所在的GridViewRow int index =gvrow.RowIndex; //獲取到行索引 RowIndex this.txt_id.Text =(GridView1.Rows[index].Cells[0].FindControl("lbl_id") asLabel).Text.Trim(); this.txt_name.Text=GridView1.Rows[index].Cells[1].Text.Trim(); this.txt_age.Text =GridView1.Rows[index].Cells[2].Text.Trim(); this.txt_grade.Text =GridView1.Rows[index].Cells[3].Text.Trim(); this.txt_address.Text =GridView1.Rows[index].Cells[4].Text.Trim(); } } }
到此,我們完成了一個手動編寫的WCF程序,我沒有講太多的原理,這個在網絡上可以搜索到很多對概念的解釋,我這個以實際操作為准,對平時學習的一個積累,如有不當之處,歡迎指出,共同學習進步。