多表查询

注意:例 如Queryable(st,sc)=> 那么 Where OrderBy Select 中就不能取其它别名 也只能用st和sc(特殊需求需要不限别名参考http://www.codeisbug.com/Doc/8/1127)

 

1.两表查询将结果返回匿名对象

var list = db.Queryable<Student, School>((st, sc) => new object[] {
        JoinType.Left,st.SchoolId==sc.Id})
      .Select((st,sc)=>new{Id=st.Id,Name=st.Name,SchoolName=sc.Name}).ToList();

生成的Sql如下:

SELECT  [st].[ID] AS [id] , 
          [st].[Name] AS [name] , 
          [sc].[Name] AS [schoolName]  FROM [STudent] st 
          Left JOIN School sc ON ( [st].[SchoolId] =[sc].[Id])


如果实体中的字段取名比较好支持自动填充(4.8.1)

var list = db.Queryable<Student, School>((st, sc) => new object[] {
        JoinType.Left,st.SchoolId==sc.Id})
      .Select<ViewModel>().ToList();
      
//sql   
SELECT  [st].[ID] AS [id] , 
          [st].[Name] AS [name] ,  
          [sc].[Name] AS [schoolName]/*ORM自动识别出这一列*/  
          FROM [STudent] st 
          Left JOIN School sc ON ( [st].[SchoolId] =[sc].[Id])
          
//class
public class ViewModel{
  public int ID{get;set;}
  public string Name{get;set;}
  public string schoolName{get;set;}//类名+Name
}




2.两表查询将结果返回到实体对象

List<VStudent> list = db.Queryable<Student, School>((st, sc) => new object[] {
        JoinType.Left,st.SchoolId==sc.Id})
       .Select((st,sc)=>new VStudent{Id=st.Id,Name=st.Name,SchoolName=sc.Name}).ToList();
public class VStudent(){
   public string Name{get;set;}
   public int Id{get;set;}
   public string  SchoolName{get;set;}
}


3.三表查询并且返回st和sc的完整对象集合 

   var list = db.Queryable<Student, School, Student>((st, sc, st2) => new object[] {
              JoinType.Left,st.SchoolId==sc.Id,
              JoinType.Left,st.SchoolId==st2.Id
            })
            .Where((st, sc, st2) => st2.Id == 1 || sc.Id == 1 || st.Id == 1)
            .OrderBy((sc) => sc.Id)
            .OrderBy((st,sc)=> st.Name,OrderByType.Desc)
            .Select((st,sc,st2)=>new { st=st,sc=sc}).ToList();
SELECT   [st].[Id] AS [Student.Id] ,
         [st].[SchoolId] AS [Student.SchoolId] ,
         [st].[Name] AS [Student.Name] ,
         [st].[CreateTime] AS [Student.CreateTime] ,
         [sc].[Id] AS [School.Id] ,
         [sc].[Name] AS [School.Name]
FROM [STudent] st
LEFT JOIN School sc
    ON ( [st].[SchoolId] =[sc].[Id])
LEFT JOIN STudent st2
    ON ( [st].[SchoolId] =[st2].[ID])
WHERE ((( [st2].[ID] = @Id0 )
        OR ( [sc].[Id] = @Id1 ))
        OR ( [st].[ID] = @Id2 ))ORDER BY [sc].[ID] ASC,[st].[Name] ASC


我们可以看出查询返回的结果是完整对象

Student st=list[0].st;
School sc=list[0].sc;


4.多表查询分页

  var list3 = db.Queryable<Student, School>((st, sc) => new object[] {
              JoinType.Left,st.SchoolId==sc.Id
            }).Select((st, sc) => new ViewModelStudent { Name = st.Name, SchoolId = sc.Id })
            .ToPageList(pageIndex,pageSize)


5.五表查询例子

  var list2 = db.Queryable<Student, School, Student, Student, Student>((st, sc, st2, st3, st4) => new object[] {
              JoinType.Left,st.SchoolId==sc.Id,
              JoinType.Left,st.Id==st2.Id,
              JoinType.Left,st.Id==st3.Id,
              JoinType.Left,st.Id==st4.Id
            })
            .Where((st,sc)=>sc.Id==1)
            .Select((st, sc, st2,st3,st4) => new { id= st.Id ,name=st.Name,st4=st4}).ToList();



6.二个Queryable的Join(4.6.0.9)

var q1 = db.Queryable<Student, School>((st,sc)=>new object[] {
                JoinType.Left,st.SchoolId==sc.Id
            }).Select((st, sc) => new ViewModelStudent4() { Id=st.Id, Name=st.Name,SchoolName=sc.Name });

var q2 = db.Queryable<School>();


var innerJoinList = db.Queryable(q1, q2, (j1, j2) => j1.Id == j2.Id).Select((j1, j2) => j1).ToList();//inner join

var leftJoinList = db.Queryable(q1, q2,JoinType.Left, (j1, j2) => j1.Id == j2.Id).Select((j1, j2) => j1).ToList();//left join


多表查询的简化

当我们不需要用LEFT JOIN或者 RIGHT JOIN 只是单纯的INNER JOIN时我们还提供了更简单的语法实现多表查询

//2表查询
var list5 = db.Queryable<Student, School>((st, sc) => st.SchoolId == sc.Id).Select((st,sc)=>new {st.Name,st.Id,schoolName=sc.Name}).ToList();

//3表查询
var list6 = db.Queryable<Student, School,School>((st, sc,sc2) => st.SchoolId == sc.Id&&sc.Id==sc2.Id)
    .Select((st, sc,sc2) => new { st.Name, st.Id, schoolName = sc.Name,schoolName2=sc2.Name }).ToList();

//3表查询分页
var list7= db.Queryable<Student, School, School>((st, sc, sc2) => st.SchoolId == sc.Id && sc.Id == sc2.Id)
.Select((st, sc, sc2) => new { st.Name, st.Id, schoolName = sc.Name, schoolName2 = sc2.Name }).ToPageList(1,2);


使用复杂模型查询

  //性能差,推荐用Mapper功能实现(http://www.codeisbug.com/Doc/8/1161)
  var students = db.Queryable<CMStudent>().ToList();
  if (students != null)
  {
       foreach (var item in students)
       {
            Console.WriteLine(item.SchoolName);
 
            Console.WriteLine(item.SchoolSingle.Name);
             
            Console.WriteLine(item.SchoolList.Count);
    }
  }

复杂模型参考:

http://www.codeisbug.com/Doc/8/1143




子查询

4.5.2.2 版本支持的写法


1. 查询一条数据

var getAll = db.Queryable<Student, School>((st, sc) => new object[] {
JoinType.Left,st.Id==sc.Id})
.Where(st => st.Id == SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id))
.ToList();
     
//生成的MYSQL语句,如果是SqlServer就是TOP 1
SELECT `st`.`ID`,`st`.`SchoolId`,`st`.`Name`,`st`.`CreateTime` 
     FROM `STudent` st Left JOIN `School` sc ON ( `st`.`ID` = `sc`.`Id` )  
      WHERE ( `st`.`ID` =(SELECT `Id` FROM `School` WHERE ( `Id` = `st`.`ID` ) limit 0,1))

在select中也可以使用

var getAll = db.Queryable<Student, School>((st, sc) => new object[] {
JoinType.Left,st.Id==sc.Id})
.Select(st =>
       new{
              name = st.Name,
              id = SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id)
       }).ToList();



2.IN和NOT IN的操作


var getAll7 = db.Queryable<Student>().Where(it => 
SqlFunc.Subqueryable<School>().Where(s => s.Id == it.Id).Any()).ToList();

//生成的SQL(等于同于it.id in(select id from school)只是写法不一样
SELECT `ID`,`SchoolId`,`Name`,`CreateTime` FROM `STudent` it 
WHERE (EXISTS ( SELECT * FROM `School` WHERE ( `Id` = `it`.`ID` ) )) 


var getAll8 = db.Queryable<Student>().Where(it => 
SqlFunc.Subqueryable<School>().Where(s => s.Id == it.Id).NotAny()).ToList();

//生成的SQL
SELECT `ID`,`SchoolId`,`Name`,`CreateTime` FROM `STudent` it  
WHERE (NOT EXISTS ( SELECT * FROM `School` WHERE ( `Id` = `it`.`ID` ) ))


3.更多操作


var getAll9= db.Queryable<Student>().Where(it => SqlFunc.Subqueryable<School>()
.Where(s => s.Id == it.Id).Max(s => s.Id) == 1).ToList();

var getAll9= db.Queryable<Student>().Where(it => SqlFunc.Subqueryable<School>()
.Where(s => s.Id == it.Id).Min(s => s.Id) == 1).ToList();

var getAll10 = db.Queryable<Student>().Where(it => SqlFunc.Subqueryable<School>()
.Where(s => s.Id == it.Id).Count() == 1).ToList();



4.4版本才支持的写法


单表

    var list9 = db.Queryable<Student>("it")
    .OrderBy(it => it.Id)
    .In(it => it.Id,db.Queryable<School>().Where("it.id=schoolId").Select(it=>it.Id))
    .ToList();

多表

    var list11 = db.Queryable<Student, School>((st, sc) => st.SchoolId == sc.Id)
     .In(st => st.Name, db.Queryable<School>().Where(it=>it.Id==1).Where("id=st.schoolid").Select(it => it.Name))
     .OrderBy(st => st.Id)
     .Select(st => st)
     .ToList();


Union all

var getUnionAllList2 = db.UnionAll(db.Queryable<Student>(), db.Queryable<Student>()).ToList();


收藏到朋友圈: