Oracle-连接查询

连接查询

Chloe 友好支持多表连接查询,一切都可以用 lambda 表达式操作,返回类型可以是自定义类型,也可以是匿名类型。强类型开发,编译可见错误,容错率高。
1.建立连接:

var user_city_province = context.Query<User>()
                         .InnerJoin<City>((user, city) => user.CityId == city.Id)
                         .InnerJoin<Province>((user, city, province) => city.ProvinceId == province.Id);

2.得到一个 IJoiningQuery 对象,就可以 Select 所需要的数据返回一个 IQuery 对象,然后就可以进行 Where、OrderBy、GroupBy、分页、聚合查询等操作:
查出一个用户及其隶属的城市和省份的所有信息:

/* 调用 Select 方法返回一个泛型为包含 User、City、Province 匿名类型的 IQuery 对象。
 * Select 方法也可以返回自定义类型 。
 */
var qq = user_city_province.Select((user, city, province) => new
{
    User = user,
    City = city,
    Province = province
});

/* 根据条件筛选,然后调用 ToList 就会返回一个泛型为 new { User = user, City = city, Province = province } 的 List 集合 */
var result = qq.Where(a => a.User.Id == 1).ToList();

/*
 * 生成的 sql:
 * SELECT "USERS"."ID" AS "ID","USERS"."NAME" AS "NAME","USERS"."GENDER" AS "GENDER","USERS"."AGE" AS "AGE","USERS"."CITYID" AS "CITYID","USERS"."OPTIME" AS "OPTIME","CITY"."ID" AS "ID0","CITY"."NAME" AS "NAME0","CITY"."PROVINCEID" AS "PROVINCEID","PROVINCE"."ID" AS "ID1","PROVINCE"."NAME" AS "NAME1" 
   FROM "USERS" "USERS" 
   INNER JOIN "CITY" "CITY" ON "USERS"."CITYID" = "CITY"."ID" 
   INNER JOIN "PROVINCE" "PROVINCE" ON "CITY"."PROVINCEID" = "PROVINCE"."ID" 
   WHERE "USERS"."ID" = 1
 */

/* 如果不想返回所有字段,得到 IQuery 对象后可以进一步 Select 指定的字段提高查询性能 
 * ##推荐使用此方式##
 */
var result1 = qq.Where(a => a.User.Id == 1)
                .Select(a => new { UserId = a.User.Id, UserName = a.User.Name, CityName = a.City.Name, ProvinceName = a.Province.Name })
                .ToList();

可以只获取指定的字段信息:

user_city_province.Select((user, city, province) => new
{
    UserId = user.Id,
    UserName = user.Name,
    CityName = city.Name,
    ProvinceName = province.Name
}).Where(a => a.UserId == 1).ToList();

/*
 * 生成的 sql 只会包含 UserId、UserName、CityName、ProvinceName 四个字段
 * SELECT "USERS"."ID" AS "USERID","USERS"."NAME" AS "USERNAME","CITY"."NAME" AS "CITYNAME","PROVINCE"."NAME" AS "PROVINCENAME" 
   FROM "USERS" "USERS" 
   INNER JOIN "CITY" "CITY" ON "USERS"."CITYID" = "CITY"."ID" 
   INNER JOIN "PROVINCE" "PROVINCE" ON "CITY"."PROVINCEID" = "PROVINCE"."ID" 
   WHERE "USERS"."ID" = 1
 */

快捷连接
框架提供了快捷连接的接口:

context.JoinQuery<User, City, Province>((user, city, province) => new object[] 
{
    JoinType.LeftJoin, user.CityId == city.Id,          /* 表 User 和 City 进行Left连接 */
    JoinType.LeftJoin, city.ProvinceId == province.Id   /* 表 City 和 Province 进行Left连接 */
})
.Select((user, city, province) => new { User = user, City = city, Province = province })  /* 投影成匿名对象 */
.Where(a => a.User.Id > -1)     /* 进行条件过滤 */
.OrderByDesc(a => a.User.Age)   /* 排序 */
.TakePage(1, 20)                /* 分页 */
.ToList();

超过5个表连接

//假设已经有5个表建立了连接的对象为 jq_q1_q5
IJoiningQuery<T1, T2, T3, T4, T5> jq_q1_q5 = null;

//jq_q1_q5 调用 Select 方法,返回一个包含 T1-T5 的 IQuery<T> 对象 view_q1_q5
var view_q1_q5 = jq_q1_q5.Select((t1, t2, t3, t4, t5) => new { T1 = t1, T2 = t2, T3 = t3, T4 = t4, T5 = t5 });

//假设第6个表的 IQuery<T6> 对象为 q6
IQuery<T6> q6 = null;

//这时,view_q1_q5 与 q6 建立连接,返回 IJoiningQuery 对象 jq
var jq = view_q1_q5.InnerJoin(q6, (t1_t5, t6) => t1_t5.T5.XX == t6.XXX);

//然后我们调用 jq 的 Select 方法,返回一个包含 T1-T6 的 IQuery<T> 对象 view。
//view 又是一个 IQuery<T> 对象,泛型参数为包含 T1-T6 所有信息的匿名对象(这时候还没有发起 sql 查询哦),拿到它,我们就可以为所欲为了。
var view = jq.Select((t1_t5, t6) => new { T1 = t1_t5.T1, T2 = t1_t5.T2, T3 = t1_t5.T3, T4 = t1_t5.T4, T5 = t1_t5.T5, T6 = t6 });

//可以直接查出数据库中 T1-T6 的所有信息
view.ToList();

//也可以选取 T1-T6 中我们想要的字段
view.Select(a => new { a.T1.xx, a.T2.xx, a.T3.xx /*...*/}).ToList();

框架亦支持左连接、右连接和Full连接查询,用法和内连接相同。