在前段时间开发的过程中,需要对两个或三个集合进行联合查询,并返回一张新的数据表,脑子里第一反应就是用LINQ实现,然后两表查询没有任何压力,但是在三表联查的时候遇到了一点问题,大概是之前没有接触过这种三个List<T>的联合查询,然后去查阅了一些资料,然后最后还是做出来了。

首先看下LINQ中提供的两个扩展方法的相同与不同:(以下内容摘自dodo的博客园)

LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展;Queryable类,针对继承了IQueryable<T>接口的集合进行扩展。我们会发现接口IQueryable<T>实际也是继承了IEnumerable<T>接口的,既然这样微软为什么要设计出两套扩展方法呢?

从LINQ查询功能上我们知道实际上可以分为三类:LINQ to OBJECTS、LINQ to SQL和LINQ to XML。其实微设计这两套接口主要是针对LINQ to OBJECTS和LINQ to SQL,两者对于查询的内部处理机制是完全不同的。针对LINQ to OBJECTS 时,使用Enumerable中的扩展方法对本地集合进行排序和查询操作,查询参数接受的是Func<>,Func<>叫做谓语表达式,相当于一个委托。针对LINQ to SQL时,则使用Queryable中的扩展方法,它接受的是Expression<>。

下面把自己写的代码贴上来,给还没搞明白的同学一个参照:

两表查询
public List<EaxmineQuestionBankDto> GetJoinEaxmineQuestionBank(List<ExamineQuestionBankEntity> examineQuestionBankEntities, List<CarClassEntity> carClassEntities)
        {
            var queryable =
                from examineQuestionBank in examineQuestionBankEntities
                from carClass in carClassEntities
                where
                carClass.Id == examineQuestionBank.CarClassId
                select
                new EaxmineQuestionBankDto
                {
                    Id = examineQuestionBank.Id,
                    CarClassId = examineQuestionBank.CarClassId,
                    CarName = carClass.CarName,
                    ExamineDetails = examineQuestionBank.ExamineDetails,
                    ExamineName = examineQuestionBank.ExamineName,
                    ExamineStandard = examineQuestionBank.ExamineStandard,
                    ExamineType = examineQuestionBank.ExamineType,
                    Remark = examineQuestionBank.Remark
                };
            return queryable.ToList();
        }
三表查询
public List<CarExamineRecordDto> GetJoinCarExamineRecord(List<CarExamineRecordEntity> carExamineRecordEntities, List<CarClassEntity> carClassEntities, List<CarEntity> carEntities)
        {
            var queryable =
                    from rPerm in carEntities.AsEnumerable()
                    join rOpera in carExamineRecordEntities.AsEnumerable()
                    on rPerm.Id equals rOpera.CarId
                    into newTable
                    from carExamineRecord in newTable.DefaultIfEmpty()
                    join rOpera2 in carClassEntities.AsEnumerable()
                    on rPerm.CarClassId equals rOpera2.Id
                    into newTable2
                    from cars in newTable2.DefaultIfEmpty()
                    select new CarExamineRecordDto
                    {
                        Id = rPerm.Id,
                        AllocationType = (carExamineRecord == null || carExamineRecord.AllocationType.ToString() == null ? 0 : carExamineRecord.AllocationType),
                        CarName = cars.CarName,
                        CarNum = rPerm.CarNum,
                        ExamineMileage = (carExamineRecord == null || carExamineRecord.ExamineMileage > 0 ? 0 : carExamineRecord.ExamineMileage),
                        ExamineTime = (carExamineRecord == null || carExamineRecord.ExamineTime == null ? Convert.ToDateTime("1999/09/09") : carExamineRecord.ExamineTime),
                        VIN = rPerm.VIN
                    };
            return queryable.ToList();
        }