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 到这里就结束了,看到这里应该已经算师父领进门了,后续的提高还要靠大家自己去琢磨。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值