项目介绍
这节将要把《一步一步学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;
|