本篇介绍Linq的Group和Join操作,继续使用《Linq 学习(3) 语法结构》中介绍的数据源。

Group
Group是进行分组操作,同SQL中的Group By类似。
原型如下:

public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>( 
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector)

它有几个重载,返回类型有两种:IEnumerable<IGrouping<TKey, TSource>> 和 IEnumerable<TResult>。
返回类型为:IEnumerable<IGrouping<TKey, TSource>>
示例:
返回按学号分组学生的成绩

var result = from score in DataSource.Scores 
             group score by score.StudentID into scoreGroup 
             select scoreGroup;

scoreGroup为IGrouping<TKey, TSource>类型,返回结果为IEnumerable<IGrouping<TKey, TSource>>,既集合的集合,因此输出时需用双重循环。
IGrouping<TKey, TElement>接口定义为:

public interface IGrouping<TKey, TElement> : IEnumerable<TElement>, IEnumerable 

    TKey Key { get; } 
}

其中Key为分组依据的字段。

foreach (var group in result) 

    //输出分组依据的字段 
    Console.WriteLine("\nStudent ID:" + group.Key);

// 输出组内成员 
    foreach (var score in group) 
    { 
        Console.WriteLine(score); 
    } 
}

// result: 
// Student ID:1 
// Student ID:1,Course ID:1,Score:78 
// Student ID:1,Course ID:2,Score:60 
// ...

// Student ID:2 
// Student ID:2,Course ID:1,Score:59 
// ...

等效的扩展方法调用实现为:

var result = DataSource.Scores.GroupBy(score => score.StudentID);

返回类型为:IEnumerable<TResult>
对分组结果进行一些包装,如包装为匿名类型。
返回按学号分组学生的成绩

var result = from score in DataSource.Scores 
             group score by score.StudentID into scoreGroup 
             select new { StudentID = scoreGroup.Key, Group = scoreGroup };

匿名类型中Group为IGrouping<TKey, TSource>类型。
等效的扩展方法调用实现为:

var result = DataSource.Scores.GroupBy(score => score.StudentID, 
    (key, group) => new { StudentID = key, Group = group });

其他一些重载使用方法类似。

Join

连接操作。

public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>( 
    this IEnumerable<TOuter> outer, 
    IEnumerable<TInner> inner, 
    Func<TOuter, TKey> outerKeySelector, 
    Func<TInner, TKey> innerKeySelector, 
    Func<TOuter, TInner, TResult> resultSelector)

从Join方法原型可以看出其使用方法。

内连接
选择左右两侧集合都含有相对应的元素。
示例:
查询学生的姓名、学科、成绩。

var result = from score in DataSource.Scores 
             join student in DataSource.Students on score.StudentID equals student.StudentID 
             join course in DataSource.Courses on score.CourseID equals course.CourseID 
             select new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = score.Value }; 
// result 
// { StudentName = Andy, CourseName = C Language, ScoreValue = 78 } 
// { StudentName = Andy, CourseName = Biophysics, ScoreValue = 60 } 
// ... 
// { StudentName = Bill, CourseName = C Language, ScoreValue = 59 } 
// { StudentName = Cindy, CourseName = Biophysics, ScoreValue = 60 } 
// ...

等效的扩展方法调用实现为:

var result = 
    DataSource.Scores.Join( 
    DataSource.Students, 
    score => score.StudentID, 
    student => student.StudentID, 
    (score, student) => new { StudentName = student.StudentID, ScoreValue = score.Value, CourseID = score.CourseID }) 
    .Join(DataSource.Courses, 
    scostu => scostu.CourseID, 
    course => course.CourseID, 
    (scostu, course) => new { StudentName = scostu.StudentName, CourseName = course.CourseName, ScoreValue = scostu.ScoreValue }); 

左外连接
当右侧的连接的右侧没有左侧对应的元素时,内连接会忽略左侧元素。要想保留左侧元素,可以使用做外连接。右侧被置为默认值,如:引用类型被置为空。
示例:

var result = 
    from student in DataSource.Students2 
    join score in DataSource.Scores on student.StudentID equals score.StudentID into Scores 
    from score in Scores.DefaultIfEmpty() 
    select new { student = student, score = score == default(Score) ? 0 : score.Value }; 
// result: 
// { student = Student ID:5,Student Name:Erik, score = 78 } 
// { student = Student ID:6,Student Name:Frank, score = 0 }

等效的扩展方法调用实现为: 
var result = 
    DataSource.Students2.GroupJoin( 
    DataSource.Scores, 
    student => student.StudentID, 
    score => score.StudentID, 
    (student, Scores) => new { student = student, Scores = Scores }) 
    .SelectMany(group => group.Scores.DefaultIfEmpty(), 
    (group, score) => new { student = group.student, score = (score == null) ? 0.0 : score.Value });

笛卡尔积
集合中的元素交错连接。
示例:统计学生课程成绩时的模板。

var result = from student in DataSource.Students 
             from course in DataSource.Courses 
             select new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = (double?)null }; 
// result: 
// { StudentName = Andy, CourseName = C Language, ScoreValue =  } 
// { StudentName = Andy, CourseName = Biophysics, ScoreValue =  } 
// ... 
// { StudentName = Bill, CourseName = C Language, ScoreValue =  } 
// ... 
// { StudentName = Cindy, CourseName = Fundamentals of Compiling, ScoreValue =  } 
// ...

等效的扩展方法调用实现为: 
var result = DataSource.Students.SelectMany( 
    student => DataSource.Courses 
        .Select( 
        course => 
            new { StudentName = student.Name, CourseName = course.CourseName, ScoreValue = (double?)null }));

GroupJoin
连接分组。
方法原型为:

public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>( 
    this IEnumerable<TOuter> outer, 
    IEnumerable<TInner> inner, 
    Func<TOuter, TKey> outerKeySelector, 
    Func<TInner, TKey> innerKeySelector, 
    Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)

// result: 
// Andy 
// 1----78 
// 2----60 
// ... 
// Bill 
// 1----59 
// ... 
// Cindy 
// 2----60 
// ...

相当于组合了Group操作和Join操作。等效的操作如下:

var result = from item in 
                 (from student in DataSource.Students 
                  join score in DataSource.Scores on student.StudentID equals score.StudentID 
                  select new { StudentName = student.Name, CourseID = score.CourseID, Value = score.Value }) 
             group item by item.StudentName into Group 
             select new { StudentName = Group.Key, Group = Group };

结束语
到现在,Linq与SQL语言等价的操作基本介绍完,组合这些操作能实现复杂的查询。

linq group join的更多相关文章

  1. Linq中join & group join & left join 的用法

    Linq中join & group join & left join 的用法 2013-01-30 11:12 12154人阅读 评论(0) 收藏 举报  分类: C#(14)  文章 ...

  2. Join, Group Join

    Linq的 Join对应SQL中的inner join,当左右两张表有匹配数据时才返回一条记录: Linq的 Group Join对应SQL中的LEFT OUTER JOIN,即使右表中没有匹配,也从 ...

  3. EF INNER JOIN,LEFT JOIN,GROUP JOIN

    IQueryable<TOuter>的扩展方法中提供了 INNER JOIN,GROUP JOIN但是没有提供LEFT JOIN GROUP JOIN适用于一对多的场景,如果关联的GROU ...

  4. EF 里的 join and Group Join

    join ); pageCount = _db.Orders.Count(); return _db.Orders.OrderByDescending(c=>c.ID).Skip(skip).T ...

  5. Using LINQ Group By and String.Join() / Aggregate() in Entity Framework 3.5

    linq to sql 的时候,有时候需要用到 先group  然后来个 aggregate 串连一下值, 但会总会出错,说不识别 aggregate 或者 string.join 方法 搜遍网络 一 ...

  6. LINQ学习笔记 Join 与 Group join

    LINQ中的Join对应T-SQL中的内连接,并无左连接的方法,当然也没有右连接. 要达成Left join必须依靠GroupJoin来完成. GroupJoin顾名思义就是先集团在做加入,加入的不同 ...

  7. linq 实现group by 不使用group关键字 等同lambad表达式中的group join 查询一对多关系

    return from orderInfo in orderEntity.x_s_orderInfo join oState in orderEntity.x_s_oStatuInfo on orde ...

  8. linq group by max 多表链接实例

    SELECT s.* FROM dbo.ERG_TipOffsInfo s, (SELECT Data,MAX(Createtime) max_Time FROM dbo.ERG_TipOffsInf ...

  9. Linq 中 Join 的用法

    Linq中连接主要有组连接.内连接.左外连接.交叉连接四种.各个用法如下. 注:本文内容主要来自<Linq实战>,本例中用到的对象请见文章底部. 1. 组连接 组连接是与分组查询是一样的. ...

随机推荐

  1. win7如何让局域网其他电脑通过IP直接访问自己电脑的网站

    一.打开控制面板 二.打开防火墙 三.点击右侧高级设置 四.点击防火墙属性 五.点击防火墙状态选择为关闭,确定 六.点击右侧允许或功能通过windows防火墙 七.执行第六部会打开防火墙通信例外窗口, ...

  2. LightOJ 1341 唯一分解定理

    Aladdin and the Flying Carpet Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld &a ...

  3. java内存空间详解

    Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识.一般 ...

  4. js 上传文件模拟Form 表单

    使用FormData对象 在本文章中 创建一个FormData对象 使用HTML表单来初始化一个FormData对象 使用FormData对象发送文件 利用FormData对象,你可以使用一系列的键值 ...

  5. ioc和aop的理解(Spring就是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。)

    IoC,(Inverse of Control)控制反转,其包含两个内容:其一是控制,其二是反转.在程序中,被调用类的选择控制权从调用它的类中移除,转交给第三方裁决.这个第三方指的就是Spring的容 ...

  6. 检测是否是IE浏览器

    浏览器识别版本方法 //使用说明返回的是一个对象{"browser":"[IE]...","version":"11.0" ...

  7. html特殊符号

    1                     ´ ´ © © > > µ µ ® ® & & ° ° ¡ ¡     » » ¦ ¦ ÷ ÷ ¿ ¿ ¬ ¬ § § • • ...

  8. SQL select结果集和return的区别

    IF EXISTS (SELECT 1 FRIN sys.objects where object_id=OBJECT_ID(N'[dbo].[testReturn_up]')AND type in ...

  9. Jenkins从2.x新建Job时多了一个文件夹的功能(注意事项)

    这个job如果在一个文件夹里面,那么想要的URL就会改变,默认会带上这个文件夹上去,所以在用[参数化构建插件]的时候要留意这个点.获取的URL将会不一样.

  10. 关于git的学习

    Git是目前世界上最先进的分布式版本控制系统(没有之一)! 由于现在用的还不多,还没有这种体会,但是前人的经验是值得借鉴的,所以我认真的学习了一些关于git的简单操作,现在在这分享一些心得,或者说是为 ...