首先看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建立关联。

  1. CREATE TABLE [dbo].[Customer](
  2. [ID] [int] NOT NULL,
  3. [Name] [nvarchar](30) )
  4. CREATE TABLE [dbo].[Purchase](
  5. [ID] [int] NOT NULL,
  6. [CustomerID] [int] NULL,
  7. [Date] [datetime] NOT NULL,
  8. [Description] [varchar](30) )

复制代码

我们来实现SQL中的三种非常经典的联接方式。

第一:cross join,它的结果集是所有表的迪卡尔积。

  1. //cross join
  2. from c in Customers
  3. from o in Purchases
  4. select o

复制代码

在LINQ TO SQL中,下面的from都指定为表名的话,就会生成下面的语句:

  1. SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price]
  2. FROM [Customer] AS [t0], [Purchase] AS [t1]

复制代码

第二:inner join。

  1. //inner join
  2. from c in Customers
  3. from o in c.Purchases
  4. select o

复制代码

生成的SQL如下:

  1. SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price]
  2. FROM [Customer] AS [t0], [Purchase] AS [t1]
  3. WHERE [t1].[CustomerID] = [t0].[ID]

复制代码

虽然没有显示的用inner join,但和它的功能是一样的.它的写法和上面的cross join看起来特别像,唯一的区别就在于cross join时,直接用了表名Purchases,而inner join用的时候变成了c.Pruchasex,即形成了一对多的情况。

第三:  LEFT OUTER JOIN

  1. from c in Customers
  2. from p in c.Purchases.DefaultIfEmpty()
  3. select new { c.Name, p.Description, Price = (decimal?) p.Price }

复制代码

生成的SQL如下:

  1. SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
  2. FROM [Customer] AS [t0]
  3. LEFT OUTER JOIN [Purchase] AS [t1] ON [t1].[CustomerID] = [t0].[ID]

复制代码

left outer join实际上是在inner join的基础上加了一个条件,利用DefaultIfEmpty(),当记录不匹配时,返回null
我们对上在的查询增加一个过滤条件。

  1. from c in Customers
  2. from p in c.Purchases.Where (p => p.Price > 1000).DefaultIfEmpty()
  3. select new
  4. {
  5. c.Name,
  6. p.Description,
  7. Price = (decimal?) p.Price
  8. }

复制代码

对应的SQL:

  1. SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
  2. FROM [Customer] AS [t0]
  3. LEFT OUTER JOIN [Purchase] AS [t1] ON ([t1].[Price] > @p0) AND ([t1].[CustomerID] = [t0].[ID])

复制代码

此时上面的语句还是标准的LEFT OUT JOIN,如果我们改变下条件的位置呢?

  1. from c in Customers
  2. from p in c.Purchases.DefaultIfEmpty()
  3. where p.Price>1000
  4. select new
  5. {
  6. c.Name,
  7. p.Description,
  8. Price = (decimal?) p.Price
  9. }

复制代码

对应的SQL:

  1. SELECT [t0].[Name], [t1].[Description] AS [Description], [t1].[Price] AS [Price]
  2. FROM [Customer] AS [t0]
  3. LEFT OUTER JOIN [Purchase] AS [t1] ON [t1].[CustomerID] = [t0].[ID]
  4. 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相关推荐

  1. LINQ TO SQL中还是用传统的连接串方式建立DbContext更好些

        首先,在LINQTOSQL中可以这样建立一个dbcontext      private TEntity GetOriginal(TEntity entity)         {       ...

  2. 在Linq to Sql中管理并发更新时的冲突(3):使用记录的时间戳进行检测

    我们描述了Linq to Sql检测在更新时是否产生了冲突的基本方法:将该记录每个字段原来的值和更新时的值进行对比,如果稍有不同则意味着记录被修改过,因此产生了更新冲突.不过您是否有这样的感觉,这种方 ...

  3. 在LINQ to SQL中使用Translate方法以及修改查询用SQL

    目前LINQ to SQL的资料不多--老赵的意思是,目前能找到的资料都难以摆脱"官方用法"的"阴影".LINQ to SQL最权威的资料自然是MSDN,但是M ...

  4. linq to sql中的自动缓存(对象跟踪)

    这篇东西应该至少一年前就写的,不过因为个人太懒,一直没记下来,今天补上. linq to sql中,对于同一个DataContext上下文环境,根据表主键选择记录时(当然这里所指的"记录&q ...

  5. 浅谈Linq to SQL中的模式

    学习Linq to SQL也有一段时间了,感叹它做为ORM虽然简单但是功能效率都还不错,从编译器和语言层面支持上来看,它是其他ORM工具不能比的.Linq to SQL中运用了很多模式对自身的效率进行 ...

  6. Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式

    当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...

  7. linq to sql 中,如何解决多条件查询问题,答案,用表达式树! (下)

    ,我们做了基于linq to sql 的多条件组合查询,但通过监视数据库发现,这样做的成本比较高,每次都要取出全部的数据到内存进行筛选.如何从真正意义上做到延迟加载,即一次只从数据库中取我们需要的用到 ...

  8. linq to sql中修改连接字符串

    如果在类库中在添加linq to sql并连接完数据库服务器后会自动生成settings.settings文件,app.config文件用于存储连接字符串(图一) 如要修改连接字符串要修改哪个还是要全 ...

  9. 也记一次性能优化:LINQ to SQL中Contains方法的优化

    距离上一篇博文更新已经两个月过去了.在此,先表一表这两个月干了些啥: 世界那么大,我也想去看看.四月份的时候,我入职了上海的一家电商公司,职位是.NET高级开发工程师.工作一个月,最大的感受是比以前小 ...

最新文章

  1. Entity Framework 重写OnModelCreating,控制生成表名的单复数
  2. 【Android 安装包优化】WebP 应用 ( libwebp 源码下载 | Android.mk 和 Application.mk 构建脚本修改 | libwebp 函数库编译 )
  3. 使用Objects判断对象是否为空,并返回对应信息
  4. 牛客多校7 - A National Pandemic(树链剖分+线段树)
  5. 最长回文子串(Longest Palindromic Substring)
  6. linux定时任务生产java服务无法执行问题群友案例
  7. android studio的 jar导入问题 ‘Android Studio Failed to Create MD5 hash for file’
  8. 前端基础-CSS如何布局以及文档流,对于新手来说,特别有用
  9. Flex(try-catch-finally)机制
  10. 比较有名的CSS,优雅地写css
  11. 广东计算机考试1级时间安排,1级计算机考试时间
  12. Javascript本地存储小结
  13. 浅谈跨平台框架 Flutter 的优势与结构 1
  14. 多元梯度下降法(2)--学习率α machine learning
  15. php验证手机号码 函数,PHP 匹配电话,手机,400号码 函数 及正则。很管用。
  16. 记一次golang cpu 占用100%
  17. 自动配置的IPv4地址怎么取消
  18. 申宝股票-大盘缩量调整
  19. alanwang[GDOU] 写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输入
  20. 如何使用iTunes制作iPhone铃声

热门文章

  1. 吃透Java中的动态代理
  2. tcp建立连接的时的几种状态
  3. golang中的nil
  4. STM32 USART串口DMA 接收和发送的源码详解!
  5. Node.js的3m安装法
  6. 前端一HTML:二十二元素显示方式案例
  7. SQL Server 死锁的告警监控
  8. Maven提高篇系列之(五)——处理依赖冲突
  9. 一些小标签(上标下标下划线等)
  10. (笔试题)将数组分成两组,使两组的和的差的绝对值最小