LINQ TO SQL 中的join(转帖)
http://www.cnblogs.com/ASPNET2008/archive/2008/12/21/1358152.html
join对于喜欢写SQL的朋友来说还是比较实用,也比较容易接受的东西。在LINQ TO SQL中,写多表查询,同样可以写join,只是它有它自己的语法要求而已,语义都是一样的,下面我来讲下LINQ TO SQL中的join最基本的形式:都是最简单的,当然还有其它方面的内容,如:怎样加上过滤条件,如何分组,如何排序等等,为了单纯说join的用法,这里就简化下。
from c in Customers join p in Purchases on c.ID equals p.CustomerID select c.Name + " bought a " + p.Description
生成的SQL:
SELECT ([t0].[Name] + @p0) + [t1].[Description] AS [value] FROM [Customer] AS [t0] INNER JOIN [Purchase] AS [t1] ON ([t0].[ID]) = [t1].[CustomerID]
通过生成的SQL,我们可以非常清晰的看出,显示的使用了inner join,它的基本要求好下: 1:包含join和on关键字,如果只有join没有on,会报语法错误。
2:外键关联时,用的是关键字equals,而不能像SQL一样用等号。
3:必须显示调用要显示的字段。即要出现select 字段,否则会报错。
LINQ TO SQL与传统SQL的相同点:
1:join的用法,并不关心主表在前还是在后,最终的结果都是相同的。上面的查询我们也可以这样写。
from p in Purchases join c in Customers on p.CustomerID equals c.ID select c.Name + " bought a " + p.Description;
2:LINQ TO SQL同样支持两表以上的关联,
from c in Customers join p in Purchases on c.ID equals p.CustomerID // first join join pi in PurchaseItems on p.ID equals pi.PurchaseID // second join select new { c.Name, p.Description, pi.Detail }
LINQ TO SQL与传统SQL的不同点:
1:LINQ TO SQL中的join,如果带有into,可以提前对表进行过滤条件的操作,而不用等到两表进行迪卡尔积产生虚似表后再进行join on的条件过滤。
Code from c in Customers join p in Purchases.Where (p2 => p2.Price > 1000) on c.ID equals p.CustomerID into custPurchases where custPurchases.Any() select new { CustName = c.Name, custPurchases }
产生的SQL:
Code SELECT [t0].[Name] AS [CustName], [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price], ( SELECT COUNT(*) FROM [Purchase] AS [t3] WHERE (([t0].[ID]) = [t3].[CustomerID]) AND ([t3].[Price] > @p0) ) AS [value] FROM [Customer] AS [t0] LEFT OUTER JOIN [Purchase] AS [t1] ON (([t0].[ID]) = [t1].[CustomerID]) AND ([t1].[Price] > @p0) WHERE EXISTS( SELECT NULL AS [EMPTY] FROM [Purchase] AS [t2] WHERE (([t0].[ID]) = [t2].[CustomerID]) AND ([t2].[Price] > @p0) ) ORDER BY [t0].[ID], [t1].[ID]
2:LINQ TO SQL包含一个groupjoin的概念,来看下MSDN对它的定义:
Queryable..::.GroupJoin 方法:基于键相等对两个序列的元素进行关联并对结果进行分组。这样情况一般都发生在一对多的情况,以主表的主键为分组对象,通过主表的主键来查询出子表的集合。
拿客人和消费记录表来说吧:一个客人会有多笔消费,我们要想得到所有客人的所有消费情况及客人姓名,即最外层的集合对象是所有客人信息,而客人的消费信息通过一个EntitySet集合来体现。在传统SQL中要想通过一个查询是做不到的,因为传统的SQL返回的只是一个具体的集合,具体记录中是不能再包含子记录的。而LINQ TO SQL则可以做到,可以通过主表记录的EntitySet属性来包含子表的集合。
var list = (from c in db.Customers join p in db.Purchases on c.ID equals p.CustomerID into custPurchases select new {custPurchases,c.Name}).ToList ();
效果图:如图一,
可以非常清楚的看出子表Puchase的内容以集合Puchase出现在最终的结果中,另外一列的内容是客户名。我们可以非常方便的取用户的某些信息。
//第一个用户的所有消费记录 List<Purchase> _list = list[0].custPurchases .ToList<Purchase >() ; //取第一个用户的第一条消费记录的价格 decimal dPrice = _list[0].Price;
可以看出LINQ模式对于开发效率还是有很大程度提高的,完全面向对象,逻辑性好,阅读性强。
对应的SQL:
SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price], ( SELECT COUNT(*) FROM [Purchase] AS [t2] WHERE ([t0].[ID]) = [t2].[CustomerID] ) AS [value], [t0].[Name] FROM [Customer] AS [t0] LEFT OUTER JOIN [Purchase] AS [t1] ON ([t0].[ID]) = [t1].[CustomerID] ORDER BY [t0].[ID], [t1].[ID]
效果图:如图二,传统SQL看起来是一个完整的集合,它没有子对象的概念。
总结:上面的所有语句都可以用等效的拉姆达表态式来代替,只不过如果是像我一样的初学者,总觉的看拉姆达表达示特别别扭,用类似SQL的语句会容易接受些。join可以和上篇文章讲的selectMany来相互转换。要想join生成LEFT OUT JOIN,同样可以用DefaultIfEmpty()来实现,有兴趣的朋友可以试下。
LINQ TO SQL 中的join(转帖)的更多相关文章
- SQL中inner join、outer join和cross join的区别
对于SQL中inner join.outer join和cross join的区别简介:现有两张表,Table A 是左边的表.Table B 是右边的表.其各有四条记录,其中有两条记录name是相同 ...
- SQL中关于Join、Inner Join、Left Join、Right Join、Full Join、On、 Where区别
前言: 今天主要的内容是要讲解SQL中关于Join.Inner Join.Left Join.Right Join.Full Join.On. Where区别和用法,不用我说其实前面的这些基本SQL语 ...
- 【转载】SQL中inner join、outer join和cross join的区别
对于SQL中inner join.outer join和cross join的区别很多人不知道,我也是别人问起,才查找资料看了下,跟自己之前的认识差不多, 如果你使用join连表,缺陷的情况下是inn ...
- LINQ to SQL 中 Concat、Union、Intersect、Except 方法的使用
Ø 前言 LINQ to SQL 中需要对两个或多个数据集进行操作,比如:合并.取交集等,主要使用下面四个方法,这四个方法都是 System.Linq.IQueryable<out T> ...
- linq to sql中的自动缓存(对象跟踪)
linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的“记录”会自动转成“对象”),如果该记录已经被select过,默认情况下会被自动缓存下来,下次 ...
- Linq to sql中使用DateDiff()
Linq to sql中使用DateDiff() 计算时间差的方法 第一种办法: from p in PurchaseLists where EntityFunctions.DiffDays(p.Cr ...
- Linq to sql中继承类映射转换问题
类型为的数据成员“Int32 VTOUID”不是类型的映射的一部分.该成员是否位于继承层次结构根节点的上方? 想躲开Linq to sql中问题限制可真是不容易: http://www.makaido ...
- sql中的join
首先准备数据 有以下数据,三张表:role(角色表).hero(英雄表).skill(技能表),我们以英雄联盟的数据做示例 一个hero对应一个role(我们这里暂定) 一个role可以对应多个her ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...
随机推荐
- java回收算法
两个最基本的java回收算法:复制算法和标记清理算法 复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B.此为新生代最常用的算法 ...
- List原理
ArrayList: ArrayList是一个可变数组实现,实现了List接口的所有方法,并允许存取null值.ArrayList基本上等同与Vector,但它只对writeObject()和read ...
- POJ 2663 Tri Tiling 矩阵快速幂 难度:3
Tri Tiling Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7841 Accepted: 4113 Descri ...
- 设置xml中控件的圆润边框效果
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...
- Java——IO类,字符缓冲区
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- MyEclipse WebSphere开发教程:WebSphere 7安装指南(四)
[周年庆]MyEclipse个人授权 折扣低至冰点!立即开抢>> [MyEclipse最新版下载] 六.管理配置文件 现在您已经安装了WebSphere 7的所有更新,您必须创建一个配置文 ...
- 2019.1.10 L223
Heavy rains that brought additional pollution downstream last year contributed to the first decline ...
- NodeJS 难点(网络,文件)的 核心 stream 二:stream是什么
对于大部分有后端经验的的同学来说 Stream 对象是个再合理而常见的对象,但对于前端同学 Stream 并不是那么理所当然,github 上甚至有一篇 9000 多 Star 的文章介绍到底什么是 ...
- 开源项目ScriptGate,Delphi与JavaScript相互调用的神器
ScriptGate是一个实现TWebBrowser上的JavaScript和Delphi代码相互调用的库,具体在这里:https://bitbucket.org/freeonterminate/sc ...
- react 学习日记
1.本地配置代理服务: create-react-app 创建的react项目 package.jsoin 中 加入: "proxy": "http://localh ...