Linq to Sql 學習系列之十 分層構架的例子

項目介紹

 

       這節將要把《一步一步學 Linq to sql (三):增刪改》中留言簿的例子修改爲使用 WCF 的多層構架。我們將會建立以下項目:

l         A ,網站項目 WebSite :留言簿表現層

l         B ,類庫項目 Contract :定義數據訪問服務的契約

l         C ,類庫項目 Service :定義數據訪問服務

l         D ,類庫項目 Entity :留言簿實體

l         E ,控制檯項目 Host :承載數據訪問服務

項目之間的引用如下:

l         A 引用 B D

l         B 引用 D System.ServiceModel 程序集

l         C 引用 B D System.ServiceModel 以及 System.Data.Linq 程序集

l         D 引用 System.Data.Linq 程序集

l         E 引用 C System.ServiceModel 程序集

 

生成映射文件和實體

 

       打開 VS2008 命令行提示,執行以下命令:

sqlmetal /conn:server=xxx;database=GuestBook;uid=xxx;pwd=xxx /map:c:/guestbook.map /code:c:/guestbook.cs /serialization:Unidirectional

       注意到,這裏我們使用了 serialization 開關,告知 sqlmetal 在生成實體的時候自動把它們標記爲 WCF 數據對象。生成結束後把 C:/GUESTBOOK.CS 添加到 Entity 項目中。

 

編寫數據訪問服務

 

       首先我們可以定義出留言簿數據訪問服務的契約(接口),把如下的代碼保存爲 IDataAccess.cs 放在 Contract 類庫項目中:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ServiceModel;

 

namespace Contract

{

    [ServiceContract ]

    public interface IDataAccess

    {

        [OperationContract ]

        void SendMessage(TbGuestBook gb);

 

        [OperationContract ]

        List <TbGuestBook > GetData();

 

        [OperationContract ]

        void DeleteMessage(string ID);

 

        [OperationContract ]

        void SendReply(TbGuestBook gb);

    }

}

       在這裏定義了四個方法:

l         創建留言

l         獲取所有留言

l         刪除留言

l         管理員發表回覆

然後,我們來實現這個契約,把如下代碼保存爲 DataAccess.cs 放在 Service 類庫項目中:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Contract;

using System.Data.Linq.Mapping;

using System.IO;

using System.ServiceModel;

 

namespace Service

{

    [ServiceBehavior (IncludeExceptionDetailInFaults = true )]

    public class DataAccess : IDataAccess

    {

        GuestBook ctx;

 

        public DataAccess()

        {

            XmlMappingSource xms = XmlMappingSource .FromXml(File .ReadAllText("c://guestbook.map" ));

            ctx = new GuestBook ("server=srv-devdbhost;database=GuestBook;uid=sa;pwd=Abcd1234" , xms);

            ctx.Log = Console .Out;

        }

 

        public void SendMessage(TbGuestBook gb)

        {

             ctx.TbGuestBook.Add(gb);

            ctx.SubmitChanges();

        }

 

        public List <TbGuestBook > GetData()

        {

            var query = from gb in ctx.TbGuestBook orderby gb.PostTime descending select gb;

            return query.ToList();

           

        }

 

        public void DeleteMessage(string ID)

        {

            TbGuestBook gb = ctx.TbGuestBook.Single(message => message.ID == new Guid (ID));

            ctx.TbGuestBook.Remove(gb);

            ctx.SubmitChanges();

        }

 

        public void SendReply(TbGuestBook gb)

        {

           //ctx.ExecuteCommand("update tbGuestBook set reply={0},isreplied=1 where ID={1}", gb.Reply, gb.ID);

            TbGuestBook record = ctx.TbGuestBook.Single(message => message.ID == gb.ID);

            record.IsReplied = true ;

            record.Reply = gb.Reply;

            ctx.SubmitChanges();

        }

    }

}

       這裏需要注意幾點:

l         我們把 DataContext 的操作在控制檯輸出

l         在進行發表回覆(更新操作)的時候,註釋的代碼和沒有註釋的代碼雖然都能完成更新操作,但是前者更合理,因爲後者會先進行 SELECT 再進行 UPDATE

 

WCF 服務端與客戶端

 

       打開 Host 項目中的 Program.cs ,使用下面的代碼來實現 WCF 的服務端:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ServiceModel;

using Service;

using Contract;

 

namespace Host

{

    class Program

    {

        static void Main(string [] args)

        {

           

            Uri uri = new Uri ("net.tcp://localhost:8080/DataAccessService" );

            using (ServiceHost sh = new ServiceHost (typeof (DataAccess ), uri))

            {

                NetTcpBinding ctb = new NetTcpBinding ();

                sh.AddServiceEndpoint(typeof (IDataAccess ), ctb, string .Empty);

                sh.Opened += delegate { Console .WriteLine(" 服務已經啓動 " ); };

                sh.Open();

                Console .ReadLine();

            }

        }

    }

}

       WebSite 項目中的 App_Code 文件夾下創建一個用戶調用服務的類, GetService.cs

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Xml.Linq;

using Contract;

using System.ServiceModel.Description;

using System.ServiceModel;

 

public class GetService

{

    public static IDataAccess GetDataAccessService()

    {

        ServiceEndpoint sep = new ServiceEndpoint (ContractDescription .GetContract(typeof (IDataAccess )),

            new NetTcpBinding (),

            new EndpointAddress ("net.tcp://localhost:8080/DataAccessService" ));

 

        ChannelFactory <IDataAccess > cf = new ChannelFactory <IDataAccess >(sep);

 

        return cf.CreateChannel();

    }

}

 

調用服務

 

       最後,就可以調用數據訪問服務來進行留言、回覆、刪除留言等操作了。頁面的代碼不再貼了,大家可以看第三篇或者下載源代碼。我們把 Default.cs 修改成如下:

public partial class _Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        {

            SetBind();

        }

    }

    protected void btn_SendMessage_Click(object sender, EventArgs e)

    {

        TbGuestBook gb = new TbGuestBook ();

        gb.ID = Guid .NewGuid();

        gb.IsReplied = false ;

        gb.PostTime = DateTime .Now;

        gb.UserName = tb_UserName.Text;

        gb.Message = tb_Message.Text;

        GetService .GetDataAccessService().SendMessage(gb);

        SetBind();

    }

    private void SetBind()

    {

        rpt_Message.DataSource = GetService .GetDataAccessService().GetData();

        rpt_Message.DataBind();

    }

}

       Admin.cs 代碼修改成如下:

public partial class Admin : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        {

            SetBind();

        }

    }

 

    private void SetBind()

    {

        rpt_Message.DataSource = GetService .GetDataAccessService().GetData();

        rpt_Message.DataBind();

    }

    protected void rpt_Message_ItemCommand(object source, RepeaterCommandEventArgs e)

    {

        if (e.CommandName == "DeleteMessage" )

        {

            GetService .GetDataAccessService().DeleteMessage(e.CommandArgument.ToString());

            SetBind();

        }

        if (e.CommandName == "SendReply" )

        {

            TbGuestBook gb = new TbGuestBook ();

            gb.ID = new Guid (e.CommandArgument.ToString());

             gb.Reply = ((TextBox )e.Item.FindControl("tb_Reply" )).Text;

            GetService .GetDataAccessService().SendReply(gb);

            SetBind();

        }

    }

}

       就這樣實現了一個多層構架的留言簿程序。對於 WCF 的一些內容本文不多作解釋了 。點擊 這裏 下載本篇代碼。
        
        如果您覺得這個例子太簡單,還可以在這裏 下載一個Linq/WCF/MVC結合使用更復雜的例子,此例的目的主要演示一個框架,實現不完整。  

       一步一步學 Linq to sql 到這裏就結束了,看到這裏應該已經算師父領進門了,後續的提高還要靠大家自己去琢磨。

發佈了7 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章