一步一步学Linq to sql(十):分层构架的例子


转自:http://kb.cnblogs.com/page/42688/

项目介绍

这节将要把《一步一步学Linq to sql(三):增删改》中留言簿的例子修改为使用WCF的多层构架。

我们将会建立以下项目:

A,网站项目WebSite:留言簿表现层

B,类库项目Contract:定义数据访问服务的契约

C,类库项目Service:定义数据访问服务

D,类库项目Entity:留言簿实体

E,控制台项目Host:承载数据访问服务

项目之间的引用如下:

A引用B和D;

B引用D和System.ServiceModel程序集

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

D引用System.Data.Linq程序集

E引用C和System.ServiceModel程序集

生成映射文件和实体
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项目中。

打开VS2008命令行提示,执行以下命令:

编写数据访问服务

首先我们可以定义出留言簿数据访问服务的契约(接口),把如下的代码保存为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);
    }
}

在这里定义了四个方法:

创建留言

获取所有留言

删除留言

管理员发表回复

然后,我们来实现这个契约,把如下代码保存为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();
        }
    }
}

这里需要注意几点:

我们把DataContext的操作在控制台输出

在进行发表回复(更新操作)的时候,注释的代码和没有注释的代码虽然都能完成更新操作,但是前者更合理,因为后者会

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

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn