0语言新特性

原文:《C# Version 3.0 Specification》,Microsoft
翻译:lover_P
查询表达式(Query
Expression)为查询提供了一种语言集成的语法,这种语法类似于关系和分级查询语言,如SQL和XQuery。

group having 分页等

var ev = OrmLiteConfig.DialectProvider.SqlExpression();


group的使用
同sql一样,注意group分组的字段要在select里

ev.Select(c => new { c.Birthday, c.Active }).Where(rn =>
rn.Birthday >= new DateTime(year, 1, 1) && rn.Birthday <=
lastDay).GroupBy(rn => new { rn.Birthday,rn.Active});


having的使用

ev.Select(c => new { c.Birthday, c.Active }).Where(rn =>
rn.Birthday >= new DateTime(year, 1, 1) && rn.Birthday <=
lastDay).GroupBy(rn => new { rn.Birthday, rn.Active
}).Having(x=>Sql.Max(x.Rate)>5);


orderby 排序
一升一降 先降后升 ordered by Rate Descending and Name Ascending
ev.Where().OrderBy(rn => new { at = Sql.Desc(rn.Rate), rn.Name })
也可以用这个OrderByDescending


Limit 分页
其实就是skip 然后take
ev.Limit(5); 默认是take 即top 5
ev.Limit(0, 4);// first page, page size=4;
ev.Limit(4, 4);// second page
ev.Limit().OrderBy(); // clear limit, clear orde

 ToCountStatement 总数
  var expr = db.From<LetterFrequency>() .Join<LetterFrequency, LetterStat>() .Where<LetterStat>(x => x.Id > 0);

var rscount= expr.ToCountStatement();//获取expr表达式结果的总数


 ev.SelectDistinct(r => r.City);
 ev.Select(r => Sql.As(Sql.Max(r.Birthday), "Birthday")); //列别名Birthday
 var r2 = db.Scalar<Author, DateTime>(e => Sql.Max(e.Birthday));Author表 DateTime类型

联接
LeftJoin

db.Column < string > ( db.From < TableA > ()
.LeftJoin < TableB >((a, b) => a.Id == b.Id)
.Where < TableB > (b => b.Id == null)
.Select(a => a.Name));

Join

db.From < TableA > ()
.Join < TableB > ()
.OrderBy(x => x.Id);

CrossJoin

db.From < CrossJoinTableA > ()
.CrossJoin < CrossJoinTableB >()
.OrderBy < CrossJoinTableA >(x => x.Id)
.ThenBy < CrossJoinTableB >(x => x.Id);




调试

db.GetLastSql().Print();

query-expression:
from-clause  query-body

from-clause:
from  from-generators

from-generators:
from-generator
from-generators  ,  from-generator

from-generator:
identifier  in  expression

query-body:
from-or-where-clausesopt  orderby-caluseopt  select-or-group-clause 
into-clauseopt

from-or-where-clauses:
from-or-where-clause
from-or-where-clauses  from-or-where-clause

from-or-where-clause:
from-clause
where-clause

where-clause:
where  boolean-expression

orderby-clause:
orderby  ordering-clauses

ordering-clauses:
ordering-clause
ordering-clauses  ,  ordering-clause

ordering-clause:
expression  ordering-directionopt

ordering-direction:
ascending
descending

select-or-group-clause:
select-clause
group-clause

select-clause:
selelct  expression

group-clause:
group  expression  by  expression

into-clause:
into  identifier  query-body

一个查询表达式以一个from子句开始,以一个select或group子句结束。起始的from子句后可以跟零个或多个from或where子句。每个from子句都是一个生成器,该生成器引入了一个可以覆盖整个序列的迭代变量;而每个where子句都是一个过滤器,该过滤器用于从结果中排出项目。最终的select或group子句根据迭代变量来指定结果的表现形式。select或group子句前面还可以有一个orderby子句,用以指定结果的顺序。最后,可以用一个into子句通过将一个查询的结果作为一个子查询的生成器来“联结”两个查询。

在查询表达式中,具有多个生成器的from子句严格等价于多个顺序的只具有一个生成器的from子句。

7.1 查询表达式的翻译

C#
3.0语言并没有为查询表达式指定确切的执行语义,而是将查询表达式翻译为对附着于查询表达式模式(Query
Expression
Pattern)的方法的调用。特别地,查询表达式分别被翻译为对名为Where、Select、SelectMany、OrderBy、OrderByDescending、ThenBy、ThenByDescending和GroupBy的方法的调用,这些方法有着预期的签名和返回值类型。这些方法既可以是待查询对象的实例方法,也可以是对象外部的扩展方法。这些方法进行着实际的查询工作。

将查询表达式翻译为方法调用的过程是一个语法映射过程,发生在任何类型绑定或重载抉择的执行之前。翻译的结果可以保证语法正确,但不一定保证产生语义正确的C#代码。在查询表达式翻译之后,产生的方法调用作为一般的方法调用进行处理,这时会依次发现错误,如方法不存在、参数类型错误或对一个范型方法的类型推断失败等。

后面的一系列示例依次演示了查询表达式的翻译。在后面的某一节中给出了翻译规则的正式描述。

7.1.1 where子句

查询表达式中的一个where子句:

from c in customers

where c.City == “London”

select c

将被翻译为对一个Where方法的调用,其参数为合并了迭代变量和where子句中的表达式所得到的拉姆达表达式:

customers.

Where(c => c.City == “London”)

7.1.2 select子句

上面的例子演示了选择了最内部的迭代变量的select子句是如何通过翻译为方法调用被消除的。

一个选择了并非最内部的迭代变量的select子句:

from c in customers

where c.City == “Longdon”

select c.Name

将被翻译为一个Select方法调用,其参数是一个拉姆达表达式:

customers.

Where(c => c.City == “London”).

Select(c => c.Name)

7.1.3 group子句

一个group子句:

from c in customers

group c.Name by c.Country

将被翻译为对GroupBy方法的调用:

customers.

GroupBy(c => c.Country, c => c.Name)

7.1.4 orderby子句

一个orderby子句:

from c in customers

orderby c.Name

select new { c.Name, c.Phone }

将被翻译为一个对OrderBy方法的调用,或者当指定了descending指示符时,被翻译为一个对OrderByDescending方法的调用:

customers.

OrderBy(c => c.Name).

Select(c => new { c.Name, c.Phone })

另一个orderby子句:

from c in customers

orderby c.Country, c.Balance descending

select new { c.Name, c.Country, c.Balance }

将被翻译为对ThenBy和ThenByDescending方法的调用:

customers.

OrderBy(c => c.Country).

ThenByDescending(c => c.Balance).

Select(c => new { c.Name, c.Country, c.Balance })

7.1.5 多重生成器

多重生成器:

from c in customers

where c.City == “London”

from o in c.Orders

where o.OrderDate.Year == 2005

select new { c.Name, o.OrderID, o.Total }

将被翻译为对所有非最内部生成器的SelectMany方法调用:

customers.

Where(c => c.City == “London”).

SelectMany(c =>

    c.Orders.

    Where(o => o.OrderDate.Year == 2005).

    Select(o => new { c.Name, o.OrderID, o.Total })

)

当多重生成器被一个orderby子句合并起来:

from c in customers, o in c.Orders

where o.OrderDate.Year == 2005

orderby o.Total descending

select new { c.Name, o.OrderID, o.Total }

一个附加的Select将被注入,用于收集排序表达式和最终的结果序列。让OrderBy可以操作整个序列是有必要的。OrderBy之后,最终的结果将被提取出来:

customers.

SelectMany(c =>

    c.Orders.

    Where(o => o.OrderDate.Year == 2005).

    Select(o => new { k1 = o.Total, v = new { c.Name, o.OrderID,
o.Total } })

).

OrderByDescending(x => x.k1).

Select(x => x.v)

7.1.6 into子句

一个into子句:

from c in customers

group c by c.Country into g

select new { Country = g.Key, CustCount = g.Group.Count() }

是嵌套查询的一种很简单的形式:

from g in

    from c in customers

发表评论

电子邮件地址不会被公开。 必填项已用*标注