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 ...
随机推荐
- EBS管理员为供应商创建新联系人流程
管理员为供应商创建新联系人流程 /oracle/apps/pos/supplier/webui/ByrAddCntctPG oracle.apps.pos.supplier.webui.ByrAddC ...
- bzoj1625
题解: 简单dp 要一维 代码: #include<bits/stdc++.h> using namespace std; ; int n,m,a[N],b[N],f[N]; int ma ...
- Flask初级(四)flash在模板中使用静态文件
Project name :Flask_Plan templates: 默认设置下,Flask在程序根目录中名为static的子目录中寻找静态文件. 随便找个图片放进去把,命令test.png Fla ...
- maven多环境配置
我们在开发项目的时候,往往会有好几个环境.比如开发.预发布(测试).产品,每个环境一般用到配置都不一样,最典型的就是数据库,开发的数据库与产品的数据库肯定是不一样的,如果要多个环境的切换就得改配置,这 ...
- Beta 冲刺(6/7)
前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10129063.html 作业博客:https://edu.cnblogs.com/campus ...
- 背景 半透明问题 rgba + filter
<html style=" background: violet;"><head><meta charset="utf-8"> ...
- Ubuntu 16.04 安装 PyCharm
https://blog.csdn.net/zhuanshu666/article/details/73554885
- [转]如何将文件夹式的项目源码导入Visual Studio
原文:https://blog.csdn.net/yangdashi888/article/details/73323419 1.把源码目录拷贝到工程目录下 2.这时在vs的目录列表里是看不到这个目录 ...
- HDU 4864
http://acm.hdu.edu.cn/showproblem.php?pid=4864 #include <iostream> #include <cstdio> #in ...
- PyTorch 数据集类 和 数据加载类 的一些尝试
最近在学习PyTorch, 但是对里面的数据类和数据加载类比较迷糊,可能是封装的太好大部分情况下是不需要有什么自己的操作的,不过偶然遇到一些自己导入的数据时就会遇到一些问题,因此自己对此做了一些小实 ...