zoukankan      html  css  js  c++  java
  • LINQ TO SQL中的selectMany(转)

    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查询的用法,其实最终的显示结果都一样,只是写法不同。

    注:
      本文示例均来自NutShell

  • 相关阅读:
    java 在线网络考试系统源码 springboot mybaits vue.js 前后分离跨域
    springboot 整合flowable 项目源码 mybiats vue.js 前后分离 跨域
    flowable Springboot vue.js 前后分离 跨域 有代码生成器 工作流
    Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    java 企业 网站源码 后台 springmvc SSM 前台 静态化 代码生成器
    java 进销存 商户管理 系统 管理 库存管理 销售报表springmvc SSM项目
    基于FPGA的电子计算器设计(中)
    基于FPGA的电子计算器设计(上)
    FPGA零基础学习:SPI 协议驱动设计
    Signal tap 逻辑分析仪使用教程
  • 原文地址:https://www.cnblogs.com/Yjianyong/p/2267801.html
Copyright © 2011-2022 走看看