ISelect动态连接多表api扩展
特性:新增apiIDynamicSelect<T>动态连接多表,并返回同一个类型的IDynamicSelect<T>
原因
- 针对一些大表多表的多条件发杂查询。
- 根据不同的参数可以动态连接表,减少不必要的连接运算。
- 当前的连接API通过From<T1,T2,T3,T4>或者ISelect<T1,T2,T3,T4,T5>做多表连接,都是预先固定对应的表。
- ISelect<A>的InnerJoin api则是固定A表连接其他B,C表,不能A连B, B连C表。
使用场景
一些OA系统或者报表之类的,会有多大几个可选参数条件,并跨越多个表筛选。但是每次查询条件不固定。
希望可以扩展原来的ISelect<T>或者新增接口IDynamicSelect<T>。
api期望如下:
interface IDynamicSelect<T1,T2,T3,T4> : IDynamicSelect<T1,T2,T3> {}
interface IDynamicSelect<T1,T2,T3> : IDynamicSelect<T1,T2> {}
interface IDynamicSelect<T1,T2> : IDynamicSelect<T1> {}
public static IDynamicSelect<T1,T2> InnerJoin<T2>(this IDynamicSelect<T1> select, Expression<Func<T1, T2, bool>> joinCondition){}
public static IDynamicSelect<T1,T2,T3> InnerJoin<T3>(this IDynamicSelect<T1, T2> select, Expression<Func<T1, T2, T3, bool>> joinCondition){}
var query = default(IDynamicSelect<T1>);
query = query.InnerJoin<T2>((t1, t2) => t1.Id == t2.Id).InnerJoin<T3>((t1, t2, t3) => t2.T3Id == t3.Id));
ISelect<T1> query = fsql.Select<T1>();
ISelect<T1, T2> query2 = query.From<T2>();
ISelect<T1, T2> query3 = query.FromQuery(
fsql.Select<T2>().Where(a => a.Id > 0)
);
ISelect<T1, Anonymous1> query3 = query.FromQuery(
fsql.Select<T2>().Where(a => a.Id > 0).WithTempQuery(a => new { a.Id, a.Name })
);
ISelect<Anonymous2, T3> query4 = query3
.WithTempQuery((a,b) => new { b.Id, b.Name, a.Code })
.From<T3>();
ISelect<Anonymous2, Anonymous3> query5 = query3
.WithTempQuery((a,b) => new { b.Id, b.Name, a.Code })
.FromQuery(
fsql.Select<T2>().Where(a => a.Id > 0).WithTempQuery(a => new { a.Id, a.Name })
);
可以参考详细的单元测试代码:https://github.com/dotnetcore/FreeSql/blob/master/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs
FromQuery是新版本的Api吗
是的,和嵌套查询一起增加的 v3.2.666
但是用FromQuery返回的ISelect<T1, T2>和ISelect<T1>没有继承或者实现的关系,不能做隐式转换。在封装api的时候就不能统一返回值了,封装不了一个动态连表查询的api
但是用
FromQuery返回的ISelect<T1, T2>和ISelect<T1>没有继承或者实现的关系,不能做隐式转换。在封装api的时候就不能统一返回值了,封装不了一个动态连表查询的api
他们都是 ISelect0,也都是 object。
单表和多表 api lambda 参数完全不一样。
建议用导航属性,就统一都是 ISelect<T> 了
接叶老板说的,这个其实应该用导航属性来实现。我这边是通过层级来加载导航属性,你也可以改成指定需要加载的导航属性来实现。
我的方案是比如我有订单 Order 表,一对多关联订单明细 OrderDetail 表,然后 OrderDetail 一对一关联产品 Product 表等等。
如果只需要加载 Order 表,查询时指定查询 Level 为 1,如果需要查询到 OrderDetail 指定 Level 为 2,查询到 Product 为 3 等等。
当然如果你明确需要查询的表,也可以通过指定查询 Order、Order.OrderDetail、Order.OrderDetail.Product 的方式来限定导航属性加载到的层级。
至于条件,在 DynamicFilterInfo 上做扩展即可,Order.FiledName 或者 Order.OrderDetail.FieldName 这样传递到后台解析。
可以参考我的 Issue:https://github.com/dotnetcore/FreeSql/issues/1113
以及提交进 FreeSql 用于测试的代码:https://github.com/dotnetcore/FreeSql/blob/4fe40d0be00515efac1e8077dcc78a37110431ef/FreeSql.Tests/FreeSql.Tests/Issues/1113.cs