一步一步学Linq to sql(十):多层架构MVC WCF Linq

前言

本次主要是使用WCF的多层架构。我们将建立以下项目:

 A,MVC网站项目 MvcOperation:留言簿表现层
 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程序集
生成映射文件和实体
打开VS2010命令行提示,执行以下命令:

sqlmetal /conn:server=.;database=GuestBook;uid=sa;pwd=saa /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
    {
        /// <summary>
        /// 添加  or 修改
        /// </summary>
        /// <param name="gb"></param>
        [OperationContract]
        void SendMessage(TbGuestBook gb);

        /// <summary>
        /// 获取所有信息
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        List<TbGuestBook> GetData();

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ID"></param>
        [OperationContract]
        void DeleteMessage(string ID);


        /// <summary>
        /// 获取一条记录
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        [OperationContract]
        TbGuestBook GetDataID(string ID);

    }
}

然后,我们来实现这个契约,把如下代码保存为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=.;database=GuestBook;uid=sa;pwd=saa", xms);
            ctx.Log = Console.Out;
        }


        public void SendMessage(TbGuestBook gb)
        {
            TbGuestBook tb =null;
            tb = GetDataID(gb.ID.ToString());
            if (tb != null)
            {
                tb.Message = gb.Message;
                tb.Reply = gb.Reply;
                tb.PostTime = gb.PostTime;
                tb.UserName = gb.UserName;
                ctx.SubmitChanges();
            }
            else
            {
                ctx.TbGuestBook.InsertOnSubmit(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.DeleteOnSubmit(gb);
            ctx.SubmitChanges();
        }

        public TbGuestBook GetDataID(string ID)
        {
            TbGuestBook record = ctx.TbGuestBook.SingleOrDefault(message => message.ID.ToString() ==ID);
            return record;
        }
    }
}

WCF服务端与客户端

 打开Host项目中的Program.cs,使用下面的代码来实现WCF的服务端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Service;
using System.ServiceModel;
using Contract;

namespace Host
{
    class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("net.tcp://localhost:880/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();
            }

        }
    }
}

在MvcOption项目中添加一个Helper文件夹下创建一个用户调用服务的类,ServerHelper.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Description;
using System.ServiceModel;
using Contract;

namespace MvcOperation.Helper
{
    public class ServerHelper
    {
        public static IDataAccess GetDataAccessService()
        {

            ServiceEndpoint sep = new ServiceEndpoint(ContractDescription.GetContract(typeof(IDataAccess)),
                new NetTcpBinding(),
                new EndpointAddress("net.tcp://localhost:880/DataAccessService"));
            ChannelFactory<IDataAccess> cf = new ChannelFactory<IDataAccess>(sep);
            return cf.CreateChannel();
        }

    }
}

最后对控制器中的代码进行修正如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Configuration;
using System.IO;
using MvcOperation.Helper;

namespace MvcOperation.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "欢迎使用 ASP.NET MVC!";
            //List<tbGuestBook> list = (from gb in ctx.tbGuestBook
            //                         orderby gb.PostTime descending 
            //                         select gb).ToList();

            return View("Index", ServerHelper.GetDataAccessService().GetData());
        }

        public ActionResult About()
        {
            return View();
        }

        public ActionResult AddBook()
        {
            return View();
        }

        public ActionResult DelBook(string id)
        {
            //tbGuestBook gb = ctx.tbGuestBook.Single(b => b.ID == new Guid(id));
            //ctx.tbGuestBook.DeleteOnSubmit(gb);
            //ctx.SubmitChanges();
            ServerHelper.GetDataAccessService().DeleteMessage(id);
            return Index();
        }

        public ActionResult UpdateBook(string id)
        {
            TbGuestBook gb = ServerHelper.GetDataAccessService().GetDataID(id);
            return View("AddBook",gb);

        }

        public ActionResult SaveBook(TbGuestBook tb)
        {
            TbGuestBook gb = null;
            if (tb.ID.ToString() != "00000000-0000-0000-0000-000000000000")
            {
                gb = ServerHelper.GetDataAccessService().GetDataID(tb.ID.ToString());
                gb.PostTime = DateTime.Now;
                gb.UserName = tb.UserName;
                gb.Message = tb.Message;
                ServerHelper.GetDataAccessService().SendMessage(gb);
                return Index();
            }
            else
            {
                tb.ID = Guid.NewGuid();
                tb.IsReplied = false;
                tb.PostTime = DateTime.Now;
                ServerHelper.GetDataAccessService().SendMessage(tb);
            }
                return Index();
        }
    }
}

示例代码下载地址http://files.cnblogs.com/aehyok/MVCLinqWCF.rar






  

posted @ 2013-04-24 12:15 aehyok 阅读(...) 评论(...) 编辑 收藏