【转】 LINQ TO SQL中的selectMany

本文介绍了如何使用LINQ实现SQL中的cross join、inner join和LEFT OUTER JOIN,并对比了几种不同的查询方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看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

资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 华为移动服务(Huawei Mobile Services,简称 HMS)是一个全面开放的移动服务生态系统,为企业和开发者提供了丰富的工具和 API,助力他们构建、运营和推广应用。其中,HMS Scankit 是华为推出的一款扫描服务 SDK,支持快速集成到安卓应用中,能够提供高效且稳定的二维码和条形码扫描功能,适用于商品扫码、支付验证、信息获取等多种场景。 集成 HMS Scankit SDK 主要包括以下步骤:首先,在项目的 build.gradle 文件中添加 HMS Core 库和 Scankit 依赖;其次,在 AndroidManifest.xml 文件中添加相机访问和互联网访问权限;然后,在应用程序的 onCreate 方法中调用 HmsClient 进行初始化;接着,可以选择自定义扫描界面或使用 Scankit 提供的默认扫描界面;最后,实现 ScanCallback 接口以处理扫描成功和失败的回调。 HMS Scankit 内部集成了开源的 Zxing(Zebra Crossing)库,这是一个功能强大的条码和二维码处理库,提供了解码、生成、解析等多种功能,既可以单独使用,也可以与其他扫描框架结合使用。在 HMS Scankit 中,Zxing 经过优化,以更好地适应华为设备,从而提升扫描性能。 通常,ScanKitDemoGuide 包含了集成 HMS Scankit 的示例代码,涵盖扫描界面的布局、扫描操作的启动和停止以及扫描结果的处理等内容。开发者可以参考这些代码,快速掌握在自己的应用中实现扫码功能的方法。例如,启动扫描的方法如下: 处理扫描结果的回调如下: HMS Scankit 支持所有安卓手机,但在华为设备上能够提供最佳性能和体验,因为它针对华为硬件进行了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值