我的WCF数据服务(二)独立
来源:互联网 发布:博客源码 编辑:程序博客网 时间:2024/06/05 18:51
由于当时正在学WCF,就使用了WCF作为数据提供,由于需要常驻内存,所以使用了WINDOWS服务作为载体。
当时觉得难点有1个,就是传递查询和排序条件,委托是不能在进程间传递的,幸亏有了 Expression 这个类,改一下参数的类型就行了,原来的代码基本不用动。但是 Expression 也不能直接就在进程间传递。后来读到了一篇文章介绍了 ExpressionSerializer 这个类,可以把表达式转换成XML,或者再转换回来。理论上可以了,就开始动手了。请看代码:
public class ModelPvd<T> : IModelPvd where T : class { protected ReaderWriterLock LockerRW = new ReaderWriterLock();//数据操作锁 protected object lockerForOp = new object();//反序列化锁 protected ExpressionSerializer serializer { private set; get; }//序列化器 public string Name { private set; get; }//类名称 protected List<T> Lm;//数据 Func<int, T> FModelPrvd;//获取实体对象的委托,在类初始化时,会获取所有数据保存在这个变量。 Action<List<T>, int> ADelDlgt;//列表删除器,当数据库删除了一条数据,也从Lm里删除这条数据。 protected ILogWriter lw;//日志记录器 public ModelPvd(Func<List<T>> dataPrvd, Func<int, T> modelPrvd, Action<List<T>, int> delDlgt, bool isAd, ILogWriter ilog) { List<Assembly> assemblies = new List<Assembly> { typeof(T).Assembly, typeof(ExpressionType).Assembly, typeof(IQueryable).Assembly }; var resolver = new TypeResolver(assemblies, new[] { typeof(T), typeof(DateTime), typeof(decimal), typeof(object) }); var knownTypeConverter1 = new KnownTypeExpressionXmlConverter(resolver); serializer = new ExpressionSerialization.ExpressionSerializer(resolver, new CustomExpressionXmlConverter[] { knownTypeConverter1 }); //上边这一段是序列化器的生成,是从ExpressionSerializer的例子里拷来的。 Lm = dataPrvd.Invoke();//获取数据 Name = typeof(T).ToString();//因为有好些数据表都要做这个功能,这个名字用来区分。 FModelPrvd = modelPrvd; ADelDlgt = delDlgt; lw = ilog; } public object[] GetList(int pageSize, int pageIndex, XElement match, XElement orderKeySelector, bool desc, out int recordCount)//查询数据功能。 { Expression<Func<T, bool>> p; lock (lockerForOp) { p = serializer.Deserialize<Func<T, bool>>(match); } lw.Write(Name + " " + p.ToString() + " l " + pageSize.ToString()); int orderWay;//排序方式,0:按照表达式排序,1,随机排序。 Expression<Func<T, int>> o = null; orderWay = orderKeySelector == null ? 1 : 0; if (orderWay == 0) { lock (lockerForOp) { o = serializer.Deserialize<Func<T, int>>(orderKeySelector); } } List<T> r; LockerRW.AcquireReaderLock(200); try { var l = Lm.Where(p.Compile()); recordCount = l.Count(); switch (orderWay) { case 1: r = l.OrderByDescending(x => Guid.NewGuid()).Take(pageSize).ToList(); break; default: if (desc) r = l.OrderByDescending(o.Compile()).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); else r = l.OrderBy(o.Compile()).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); break; } } finally { LockerRW.ReleaseReaderLock(); } if (r == null) return null; return r.ToArray(); } //////查询符合条件的数据数量。 public int GetCount(XElement match) { int rst; Expression<Func<T, bool>> p; lock (lockerForOp) { p = serializer.Deserialize<Func<T, bool>>(match); } lw.Write(Name + " " + p.ToString() + "c"); LockerRW.AcquireReaderLock(200); try { rst = Lm.Count(p.Compile()); } finally { LockerRW.ReleaseReaderLock(); } return rst; } 某一条数据发生变化(增删改)时,调用这个方法同步。 public bool UpdateData(int Id) { var model = FModelPrvd.Invoke(Id); LockerRW.AcquireWriterLock(1000); try { ADelDlgt.Invoke(Lm, Id); if (model != null) Lm.Add(model); } finally { LockerRW.ReleaseWriterLock(); } return true; } }
下面是实现的接口。
public interface IModelPvd { string Name { get; } object[] GetList(int pageSize, int pageIndex, XElement match, XElement orderKeySelector, bool desc, out int recordCount); int GetCount(XElement match); bool UpdateData(int Id); }
在WCF的服务实现类里,代码是这样的:
public class Service1 : IService1 { static List<IModelPvd> Limp; static LogWriter Lw = new LogWriter(); static Service1() { GetAllData(); } static void GetAllData() { Limp = new List<IModelPvd>(); Limp.Add(new ModelPvdAd<Model.XXX>(DAL.XXX.GetListByDAL, DAL.XXX.GetModel, (x, y) => x.RemoveAll(z => z.Id == y), Lw)); } public int GetCount(string typeName, XElement match) { var m = Limp.Find(x => x.Name == typeName); if (m != null) return m.GetCount(match); else return 0; } public object[] GetList(string typeName, int pageSize, int pageIndex, XElement match, XElement orderKeySelector, bool desc, out int recordCount) { var m = Limp.Find(x => x.Name == typeName); if (m != null) return m.GetList(pageSize, pageIndex, match, orderKeySelector, desc, out recordCount); else { recordCount = 0; return null; } } public bool UpdateData(string typeName, int Id) { var m = Limp.Find(x => x.Name == typeName); if (m != null) return m.UpdateData(Id); else return false;} }
还有WCF的接口代码:
public interface IService1{[OperationContract] [ServiceKnownType(typeof(Model.XXX))] object[] GetList(string typeName, int pageSize, int pageIndex, XElement match, XElement orderKeySelector, bool desc, out int recordCount); [OperationContract] int GetCount(string typeName, XElement match); [OperationContract] bool UpdateData(string typeName, int Id);}
上边这几段代码,是服务器端。ExpressionSerializer 这个类会把传过来的 XML 转化成原始的LAMBDA表达式,一个 Expression<<Func<Model.XXX,bool>>
这样的条件表达式,或者一个 Expression<Func<Model.XXX,int>>
这样的排序表达式。如果想随机排序,就把排序的 XML 传个 null 过来。
再来看看客户端:
public class ModelPvd<T> where T : class { protected object locker = new object();//序列化锁 protected ExpressionSerializer serializer { private set; get; }//序列化器 public string Name { private set; get; }//类名称 public Expression<Func<T, int>> PrimaryKey; public ModelPvd(Expression<Func<T, int>> primaryKey) { List<Assembly> assemblies = new List<Assembly> { typeof(T).Assembly, typeof(ExpressionType).Assembly, typeof(IQueryable).Assembly }; var resolver = new TypeResolver(assemblies, new[] { typeof(T), typeof(DateTime), typeof(decimal), typeof(object) }); var knownTypeConverter1 = new KnownTypeExpressionXmlConverter(resolver); serializer = new ExpressionSerialization.ExpressionSerializer(resolver, new CustomExpressionXmlConverter[] { knownTypeConverter1 }); Name = typeof(T).ToString(); PrimaryKey = primaryKey; } public List<T> GetList<Tm>(int pageSize, int pageIndex, Expression<Func<T, bool>> Efma, Expression<Func<T, Tm>> orderBy, bool desc, out int recordCount) { System.Xml.Linq.XElement xmlOrder = null; if ((typeof(Tm) != typeof(int)) || orderBy == null) { xmlOrder = null; } else { lock (locker) { xmlOrder = serializer.Serialize(orderBy); } } System.Xml.Linq.XElement xmlPredicate; lock (locker) { xmlPredicate = serializer.Serialize(Efma); } DataCenter.Service1Client Dcsc = All.GetDataCenterService(); object[] l = Dcsc.GetList(typeof(T).ToString(), pageSize, pageIndex, xmlPredicate, xmlOrder, desc, out recordCount) as object[]; All.CloseDc(Dcsc); var Lado = new List<T>(); foreach (object i in l) { Lado.Add(i as T); } return Lado; } public int GetCount(Expression<Func<T, bool>> Efma, bool IsRebuild = true) { System.Xml.Linq.XElement xmlPredicate; lock (locker) { xmlPredicate = serializer.Serialize(Efma); } DataCenter.Service1Client Dcsc = All.GetDataCenterService(); int rst = Dcsc.GetCount(typeof(T).ToString(), xmlPredicate); All.CloseDc(Dcsc); return rst; } public bool UpdateData(int id) { DataCenter.Service1Client Dcsc = All.GetDataCenterService(); var l = Dcsc.UpdateData(typeof(T).ToString(), id); All.CloseDc(Dcsc); return l; } }
具体的BLL.XXX 里,代码是这样的:
static ModelPvdAd<Model.XXX> Pvd = new ModelPvdAd<Model.XXX>(x => x.Id); public List<Model.XXX> GetList(int pageSize, int pageIndex, Expression<Func<Model.XXX, bool>> Efma, Expression<Func<Model.XXX, int>> orderBy, bool desc, out int recordCount) { return Pvd.GetList(pageSize, pageIndex, Efma, orderBy, desc, out recordCount); }
这样就基本完成了,建个测试页面试一下。
Expression<Func<Model.XXX,bool>> q = x=>x.id>3 && x.id<100;int rc;var l = BLL.XXX.GetList(30,1,q,x=>x.id,true,out rc);
绑定到 Repeater 没有问题。
但是继续测试的时候遇到了问题。一旦表达式中含有变量,服务端就报错了。比如上边的例子改成:
int i=3,j=100,rc;var l = BLL.XXX.GetList(30,1,x=>x.id>i && x.id<j,x=>x.id,true,out rc);
这样就不行了,原因是 表达式中的 i 和 j 在传递的时候,是临时类的变量,而不是 3 和 100。
要想知道我怎么解决的,看下一篇吧。
0 0
- 我的WCF数据服务(二)独立
- 我的WCF数据服务(一)瓶颈
- 我的WCF数据服务(三)胜利
- 我的WCF数据服务(四)涅槃
- (2) 第二章 WCF服务与数据契约 服务契约详解(二)- 如何引用WCF提供的服务
- WCF学习笔记(2)——独立WCF服务
- WCF中的REST架构二 (支持AJAX的WCF服务 - 创建服务)
- 在Sharepoint2010的Webpart中调用WCF服务(二)创建webpart并调用WCF服务
- 关于java调用.Net WCF服务的讲解(二)
- 【WCF】WCF RESTful(二)——搭建一个REST的服务
- 【WCF系列】之二:构建WCF的服务架构
- WCF(2)我的第一个WCF程序,(解决方案结构、服务契约定义、服务契约定义等)
- 简单的实例来理解WCF 数据服务(WCF DS)
- WCF实战Dome(二)--使用IIS发布WCF服务
- WCF入门教程(二)从零做起-创建WCF服务
- 创建Wcf数据服务的事例
- WCF RIA 服务 (二)- 解决方案结构
- WCF 简单架构(二) 实现服务
- Spring Boot 拦截器
- 二,Shiro概述(2)
- 编译编码问题
- python-netsnmp扩展(2)管理端简单功能开发
- svn: E175002: REPORT of '/xxxx-demo/!svn/vcc/default': Could not read response body: Secure connecti
- 我的WCF数据服务(二)独立
- mysql my.ini 配置
- HTML5 绘制简单圆形 loading. . . .
- Linux在有ipv6接入环境下优先使用ipv4
- Android application详解与用法
- UITextFeild
- 搭建开源论坛之JForum安装+简易二次修改
- Android NDK教程<->-- 简介
- Resource注解(重要)