Original (原创) by Teddy’s Knowledge Base
(1) WCF Configuration Centralization (WCF配置集中管理)
(2) WCF Automatic Deployment (WCF自动化部署)
(3) WCF Automatic Service Locating (WCF自动化服务定位)
(4) WCF Database Paging & Sorting (WCF数据库分页和排序)
(5) WCF Based ASP.NET DataSouce Control (基于WCF的数据源控件)
(6) 1 + 2 + 3 + 4 + 5 = ?
本文提供一种支持跨WCF通讯的数据库端分页和排序(以及更多超过你预期的功能)方案。
已经有很多数据库端分页和排序的实现方案了,从微软的LINQ to SQL和Entity Framework到无数的ORM框架和基于存储过程的分页和排序实现。
但是,构架得很好的支持跨WCF通信的数据库端分页和排序方案还很少见到。大多数数据库端分页和排序方案要么依赖于不能被序列化的对象,要么暴露了太多SQL相关的信息给客户端,甚至可能允许客户程序直接构造SQL或伪SQL片段,这样就不能很好的避免SQL注入。
所以,我们是在创新而不是重新造轮子。
下面是这个跨WCF通信的分页排序方案的功能列表:
1 public class TestCriteria : Criteria
2 {
3 public TestCriteria()
4 : base ( " TestTable " , " Test " )
5 {
6 }
7
8 public BooleanColumn BooleanColumn = new BooleanColumn( " BooleanColumn " );
9 public ByteColumn ByteColumn = new ByteColumn( " ByteColumn " );
10 public Int16Column Int16Column = new Int16Column( " Int16Column " );
11 public Int32Column Int32Column = new Int32Column( " Int32Column " );
12 public Int64Column Int64Column = new Int64Column( " Int64Column " );
13 public DateTimeColumn DateTimeColumn = new DateTimeColumn( " DateTimeColumn " );
14 public StringColumn StringColumn = new StringColumn( " StringColumn " , true );
15 public GuidColumn GuidColumn = new GuidColumn( " GuidColumn " );
16 public DoubleColumn DoubleColumn = new DoubleColumn( " DoubleColumn " );
17 public DecimalColumn DecimalColumn = new DecimalColumn( " DecimalColumn " );
18 }
19
20 var criteria = new TestCriteria();
21 criteria.MaxResults( 10 ).AddSortBy(criteria.Int32Column, true ).AddSortBy(criteria.StringColumn, false );
22 criteria.And(criteria.Int32Column == 1 ).Or(criteria.StringColumn.Like( " test " ));
23
24 criteria.AddResultColumn(DateTimeColumn).AddResultColumn((criteria.Int32Column + 1 ).As( " ID " )).AddResultColumn(criteria.StringColumn.As( " Name " ));
25 criteria.SkipResults( 10 );
26 criteria.Distinct();
27
28 var queryResult = aWcfService.Query(criteria);
这些类的结构和上面的查询示例代码可能和大多数SQL风格的查询语言很相似,真正的实现难点其实在如何使他们能够作为WCF服务的参数被序列化。下面的要点能帮助实现这个目标:
1 [DataContract]
2 [KnownType( typeof (BooleanColumn))]
3 [KnownType( typeof (ByteColumn))]
4 [KnownType( typeof (Int16Column))]
5 [KnownType( typeof (Int32Column))]
6 [KnownType( typeof (Int64Column))]
7 [KnownType( typeof (DateTimeColumn))]
8 [KnownType( typeof (StringColumn))]
9 [KnownType( typeof (GuidColumn))]
10 [KnownType( typeof (DoubleColumn))]
11 [KnownType( typeof (DecimalColumn))]
12 [KnownType( typeof (Condition))]
13 [KnownType( typeof (NullExpression))]
14 [KnownType( typeof (BooleanExpression))]
15 [KnownType( typeof (ByteExpression))]
16 [KnownType( typeof (Int16Expression))]
17 [KnownType( typeof (Int32Expression))]
18 [KnownType( typeof (Int64Expression))]
19 [KnownType( typeof (DateTimeExpression))]
20 [KnownType( typeof (StringExpression))]
21 [KnownType( typeof (GuidExpression))]
22 [KnownType( typeof (DoubleExpression))]
23 [KnownType( typeof (DecimalExpression))]
24 [KnownType( typeof (ExpressionCollection))]
25 [KnownType( typeof (BooleanParameterExpression))]
26 [KnownType( typeof (ByteParameterExpression))]
27 [KnownType( typeof (Int16ParameterExpression))]
28 [KnownType( typeof (Int32ParameterExpression))]
29 [KnownType( typeof (Int64ParameterExpression))]
30 [KnownType( typeof (DateTimeParameterExpression))]
31 [KnownType( typeof (StringParameterExpression))]
32 [KnownType( typeof (GuidParameterExpression))]
33 [KnownType( typeof (DoubleParameterExpression))]
34 [KnownType( typeof (DecimalParameterExpression))]
35 public class Criteria
36 {
37 // …
38
39 }
因为上面讨论的类都不是只能用于特定数据库访问组件的,所以,一个criteria可以被认为是一个查询的元数据,可以被翻译为任意一个实际的数据访问实现。例如,翻译成LINQ to SQL查询语言或者翻译成一个能直接执行的DbCommand。
//我是结尾符,待续…