【转】 LINQ TO SQL中的selectMany
首先看SelectMany的定义:
Queryable中的SelectMany 方法:将序列的每个元素投影到一个 IEnumerable<(Of <(T>)>) 并将结果序列组合为一个 IQueryable<(Of <(T>)>) 类型的序列。(引用MSDN)
在用LINQ TO SQL 来写查询语句时,有一个selectMany的语句,它标示着一对多的关系,这篇文章我想说下在LINQ TO SQL中几种可以等同selectMany的用法。
系统转换成selectMany的条件:
1:语句中不包含join ,into;
2:需要2个以上的from:下面以两个表为例:如第一个表from c in 表1
1):如果from的对象均用表名,(from c in 表2),则会转换成cross join;
2):如果第二个表名以第一个表的子表形式出现,即类似c.表2,这又分两种情况,
1>:from o in c.表2,此时会形成inner join
2>:from p in c.表2.DefaultIfEmpty(),此时会形成LEFT OUT JOIN
文中例子表结构说明:Customer表和Purchase表,通过ID与CustomerID建立关联。
- CREATE TABLE [dbo].[Customer](
- [ID] [int] NOT NULL,
- [Name] [nvarchar](30) )
- CREATE TABLE [dbo].[Purchase](
- [ID] [int] NOT NULL,
- [CustomerID] [int] NULL,
- [Date] [datetime] NOT NULL,
- [Description] [varchar](30) )
复制代码
我们来实现SQL中的三种非常经典的联接方式。
第一:cross join,它的结果集是所有表的迪卡尔积。
- //cross join
- from c in Customers
- from o in Purchases
- select o
复制代码
在LINQ TO SQL中,下面的from都指定为表名的话,就会生成下面的语句:
- SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price]
- FROM [Customer] AS [t0], [Purchase] AS [t1]
复制代码
第二:inner join。
- //inner join
- from c in Customers
- from o in c.Purchases
- select o
复制代码
生成的SQL如下:
- SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price]
- FROM [Customer] AS [t0], [Purchase] AS [t1]
- WHERE [t1].[CustomerID] = [t0].[ID]
复制代码
虽然没有显示的用inner join,但和它的功能是一样的.它的写法和上面的cross join看起来特别像,唯一的区别就在于cross join时,直接用了表名Purchases,而inner join用的时候变成了c.Pruchasex,即形成了一对多的情况。
第三: LEFT OUTER JOIN
- from c in Customers
- from p in c.Purchases.DefaultIfEmpty()
- select new { c.Name, p.Description, Price = (decimal?) p.Price }
复制代码
生成的SQL如下:
- SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
- FROM [Customer] AS [t0]
- LEFT OUTER JOIN [Purchase] AS [t1] ON [t1].[CustomerID] = [t0].[ID]
复制代码
left outer join实际上是在inner join的基础上加了一个条件,利用DefaultIfEmpty(),当记录不匹配时,返回null
我们对上在的查询增加一个过滤条件。
- from c in Customers
- from p in c.Purchases.Where (p => p.Price > 1000).DefaultIfEmpty()
- select new
- {
- c.Name,
- p.Description,
- Price = (decimal?) p.Price
- }
复制代码
对应的SQL:
- SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
- FROM [Customer] AS [t0]
- LEFT OUTER JOIN [Purchase] AS [t1] ON ([t1].[Price] > @p0) AND ([t1].[CustomerID] = [t0].[ID])
复制代码
此时上面的语句还是标准的LEFT OUT JOIN,如果我们改变下条件的位置呢?
- from c in Customers
- from p in c.Purchases.DefaultIfEmpty()
- where p.Price>1000
- select new
- {
- c.Name,
- p.Description,
- Price = (decimal?) p.Price
- }
复制代码
对应的SQL:
- SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
- FROM [Customer] AS [t0]
- LEFT OUTER JOIN [Purchase] AS [t1] ON [t1].[CustomerID] = [t0].[ID]
- WHERE [t1].[Price] > @p0
复制代码
条件改变位置后并没有改变join的本质,还是LEFT OUT JOIN,只不过查询的结果不一样了,从结果集上看,后面一种的效果和inner join的结果一样。
总结:上面的查询语句也可以用显示的join来查询,个人更喜欢用显示的join,因为相比较SQL更接近些,看起来要亲近些。在下篇文章中,我会总结显示用join查询的用法,其实最终的显示结果都一样,只是写法不同。
文/姜敏 出处/博客园
转载于:https://www.cnblogs.com/JosephLiu/archive/2010/02/28/1675063.html
【转】 LINQ TO SQL中的selectMany相关推荐
- LINQ TO SQL中还是用传统的连接串方式建立DbContext更好些
首先,在LINQTOSQL中可以这样建立一个dbcontext private TEntity GetOriginal(TEntity entity) { ...
- 在Linq to Sql中管理并发更新时的冲突(3):使用记录的时间戳进行检测
我们描述了Linq to Sql检测在更新时是否产生了冲突的基本方法:将该记录每个字段原来的值和更新时的值进行对比,如果稍有不同则意味着记录被修改过,因此产生了更新冲突.不过您是否有这样的感觉,这种方 ...
- 在LINQ to SQL中使用Translate方法以及修改查询用SQL
目前LINQ to SQL的资料不多--老赵的意思是,目前能找到的资料都难以摆脱"官方用法"的"阴影".LINQ to SQL最权威的资料自然是MSDN,但是M ...
- linq to sql中的自动缓存(对象跟踪)
这篇东西应该至少一年前就写的,不过因为个人太懒,一直没记下来,今天补上. linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的"记录&q ...
- 浅谈Linq to SQL中的模式
学习Linq to SQL也有一段时间了,感叹它做为ORM虽然简单但是功能效率都还不错,从编译器和语言层面支持上来看,它是其他ORM工具不能比的.Linq to SQL中运用了很多模式对自身的效率进行 ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...
- linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)
,我们做了基于linq to sql 的多条件组合查询,但通过监视数据库发现,这样做的成本比较高,每次都要取出全部的数据到内存进行筛选.如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到 ...
- linq to sql中修改连接字符串
如果在类库中在添加linq to sql并连接完数据库服务器后会自动生成settings.settings文件,app.config文件用于存储连接字符串(图一) 如要修改连接字符串要修改哪个还是要全 ...
- 也记一次性能优化:LINQ to SQL中Contains方法的优化
距离上一篇博文更新已经两个月过去了.在此,先表一表这两个月干了些啥: 世界那么大,我也想去看看.四月份的时候,我入职了上海的一家电商公司,职位是.NET高级开发工程师.工作一个月,最大的感受是比以前小 ...
最新文章
- Entity Framework 重写OnModelCreating,控制生成表名的单复数
- 【Android 安装包优化】WebP 应用 ( libwebp 源码下载 | Android.mk 和 Application.mk 构建脚本修改 | libwebp 函数库编译 )
- 使用Objects判断对象是否为空,并返回对应信息
- 牛客多校7 - A National Pandemic(树链剖分+线段树)
- 最长回文子串(Longest Palindromic Substring)
- linux定时任务生产java服务无法执行问题群友案例
- android studio的 jar导入问题 ‘Android Studio Failed to Create MD5 hash for file’
- 前端基础-CSS如何布局以及文档流,对于新手来说,特别有用
- Flex(try-catch-finally)机制
- 比较有名的CSS,优雅地写css
- 广东计算机考试1级时间安排,1级计算机考试时间
- Javascript本地存储小结
- 浅谈跨平台框架 Flutter 的优势与结构 1
- 多元梯度下降法(2)--学习率α machine learning
- php验证手机号码 函数,PHP 匹配电话,手机,400号码 函数 及正则。很管用。
- 记一次golang cpu 占用100%
- 自动配置的IPv4地址怎么取消
- 申宝股票-大盘缩量调整
- alanwang[GDOU] 写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输入
- 如何使用iTunes制作iPhone铃声