走进Linq-Linq to SQL How do I(2)
[1] 走进Linq-Linq to SQL How do I(2)
[2] 走进Linq-Linq to SQL How do I(2)
[3] 走进Linq-Linq to SQL How do I(2)
[4] 走进Linq-Linq to SQL How do I(2)
[2] 走进Linq-Linq to SQL How do I(2)
[3] 走进Linq-Linq to SQL How do I(2)
[4] 走进Linq-Linq to SQL How do I(2)
系列文章导航:
不能不说的C#特性-迭代器(下),yield以及流的延迟计算
走进Linq-Linq to SQL How do I(1)
走进Linq-Linq to SQL How do I(2)
走进Linq-Linq to SQL How do I(3)
走进Linq-Linq to SQL源代码赏析 Table
走进Linq-Linq to SQL源代码赏析之Provider的初始化
走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
生成的SQL语句是:
大家看到,Linq to SQL使用inner join子句。
但是Linq to SQL在使用join的时候并不是像SQL那样宽松,把上面的SQL语句贴下来:
SELECT [t0].[blogname] AS [BlogName],[t1].[Title] AS [PostTitle],[t1].[Body] AS [PostBody] FROM [blogs] AS [t0] INNER JOIN [posts] AS [t1] ON [t0].[blogid] = [t1].[BlogId] WHERE [t1].[postid] = @p0
在
SQL语句里,ON子句的[t0].[blogid] = [t1].[BlogId]左右次序是没有关系的:[t0].[blogid] = [t1].[BlogId]或[t1].[BlogId] = [t0].[blogid]的结果是一样的,但是在Linq to SQL里并不是如此,她要求查询的对象和ON子句里面的东西的位置是一一对应的:如上图,用框子框起来的四部分,橙黄色的两个,蓝色的两个,位置都是一一对应的,blog排在第一位,那么blog.Id就要排在on的第三位,1,3和2,4这种对应关系。这又是为什么呢?因为这种查询表达式最后要被转换成方法调用,而扩展方法Join的原型是:
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>
(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
大家看到没,第一个参数和第三个参数都是outer相关的,第二个参数和第四个参数都是inner相关的,最后一个是on条件时的条件运算符,如:equals。将上面的方法原型和上面那张图对应:blogs就是这里的outer,而blog.Id对应着这里的outerKeySelector,posts就是这里的inner,post.BlogId对应着这里的innerKeySelector,equals就是这里的resultSelector。实际上,如果你使用VisualStudio2008编写代码的时候,如果不按照这个顺序敲入代码,vs是不会给你智能感知的。
(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
大家也许发现上面的join生成的SQL语句只有inner join(inner join也称之为等值连接,只返回两个表联结字段相等的行),在我们这个需求里,这样使用是合理的:查找一篇文章,如果该文章对应的博客不存在的话,这篇文章也不应该显示。但是,如果我们期望使用outer join咋办呢?Linq为我们提供了一个DefaultIfEmpty()的扩展方法:
var result = from post in posts
join blog in blogs on post.BlogId equals blog.Id into joinblogs
from joinblog in joinblogs.DefaultIfEmpty()
where post.Id == 2
select new {
BlogName = joinblog.Name,
PostTitle = post.Title,
PostBody = post.Body
};
这样生成的SQL语句就是这样的了:join blog in blogs on post.BlogId equals blog.Id into joinblogs
from joinblog in joinblogs.DefaultIfEmpty()
where post.Id == 2
select new {
BlogName = joinblog.Name,
PostTitle = post.Title,
PostBody = post.Body
};
看到上面说了那么多,也许有人会问:一般的ORM框架都能在对象之间建立关系来反映数据库之间的关系,而操作的时候这种关联是自动的,难道Linq to SQL必须让程序员手动的使用这种join的方式来处理对象之间的关系么?答案是否定的。