FreeSql icon indicating copy to clipboard operation
FreeSql copied to clipboard

ISelect动态连接多表api扩展

Open ROMYIM opened this issue 3 years ago • 7 comments

特性:新增apiIDynamicSelect<T>动态连接多表,并返回同一个类型的IDynamicSelect<T>

原因

  1. 针对一些大表多表的多条件发杂查询。
  2. 根据不同的参数可以动态连接表,减少不必要的连接运算。
  3. 当前的连接API通过From<T1,T2,T3,T4>或者ISelect<T1,T2,T3,T4,T5>做多表连接,都是预先固定对应的表。
  4. 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));

ROMYIM avatar Sep 02 '22 02:09 ROMYIM

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 })
    );

2881099 avatar Sep 02 '22 03:09 2881099

可以参考详细的单元测试代码:https://github.com/dotnetcore/FreeSql/blob/master/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs

2881099 avatar Sep 02 '22 03:09 2881099

FromQuery是新版本的Api吗

ROMYIM avatar Sep 02 '22 04:09 ROMYIM

是的,和嵌套查询一起增加的 v3.2.666

2881099 avatar Sep 02 '22 07:09 2881099

但是用FromQuery返回的ISelect<T1, T2>ISelect<T1>没有继承或者实现的关系,不能做隐式转换。在封装api的时候就不能统一返回值了,封装不了一个动态连表查询的api

ROMYIM avatar Sep 08 '22 03:09 ROMYIM

但是用FromQuery返回的ISelect<T1, T2>ISelect<T1>没有继承或者实现的关系,不能做隐式转换。在封装api的时候就不能统一返回值了,封装不了一个动态连表查询的api

他们都是 ISelect0,也都是 object。

单表和多表 api lambda 参数完全不一样。

建议用导航属性,就统一都是 ISelect<T> 了

2881099 avatar Sep 08 '22 03:09 2881099

接叶老板说的,这个其实应该用导航属性来实现。我这边是通过层级来加载导航属性,你也可以改成指定需要加载的导航属性来实现。

我的方案是比如我有订单 Order 表,一对多关联订单明细 OrderDetail 表,然后 OrderDetail 一对一关联产品 Product 表等等。

如果只需要加载 Order 表,查询时指定查询 Level 为 1,如果需要查询到 OrderDetail 指定 Level 为 2,查询到 Product 为 3 等等。

当然如果你明确需要查询的表,也可以通过指定查询 OrderOrder.OrderDetailOrder.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

hd2y avatar Sep 09 '22 02:09 hd2y