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 ...
随机推荐
- jquery插件Loadmask
Loadmask是一个jquery plugin,使用此插件可以在DOM元素加载或更改内容时为此DOM元素添加一个屏蔽层,以防止用户互动,同时起到提醒用户后台任务正在运行的作用. 它可实现的效果:
- C语言按行读文件及字符串分割
#include<stdio.h> #include<iostream> using namespace std; int main() { char s[50]; char ...
- iOS UI-AlertView(警示框)和ActionSheet(选择框、操作表单)
#import "ViewController.h" @interface ViewController ()<UIAlertViewDelegate,UIActionShe ...
- OC Copy基本使用(深拷贝和浅拷贝)
首先,什么是copy? Copy的字面意思是“复制”.“拷贝”,是一个产生副本的过程. 常见的复制有:文件复制,作用是利用一个源文件产生一个副本文件. 特点:1.修改源文件的内容,不会影响副本文件: ...
- Spark任务提交底层原理
Driver的任务提交过程 1.Driver程序的代码运行到action操作,触发了SparkContext的runJob方法.2.SparkContext调用DAGScheduler的runJob函 ...
- 管道pipe与dup结合使用
前面的例子中,子进程可以直接共享父进程的文件描述符.但是如果子进程调用exec函数执行另一个应用程序时,就不能再共享了. 这种情况下可以将子进程中的文件描述符重定向到标准输入,当新执行的程序从标准输入 ...
- java web中的多条件查询
转自:http://blog.csdn.net/xulu_258/article/details/46623317 所谓多条件查询即为用户输入想要查询的条件,然后根据用户输入的条件进行查询. 当用户有 ...
- Arithmometer: A Node.js implementation
Foreword: This project is a part of pair programming task. We implement an command-line based arithm ...
- Kotlin Reference (十二) Extensions
most from reference Kotlin与C#和Gosu类似,提供了扩展一个新功能的类,而不必继承类或使用任何类型的设计模式,如Decorator(装饰者模式).这是通过称为扩展的特殊声明 ...
- UI基础:UI中类的继承关系图,最基本的视图分析
首先,UI中常用的UIwindow.UILabel.UIButton.UITextField属于UIView的子类.UITextField和UILabel和UIwindow自身没有初始化方法,需要使用 ...