From b5b67f1dcf29799364fc313d249b05b75d48e5d9 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 19 Dec 2024 17:00:55 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=BF=A7=E5=8C=96=20DateTime.Subtract(date?= =?UTF-8?q?).TotalDays=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=20datediff(day,=20date1,=20date2)=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/FreeSql.xml | 1230 +++++++---------- FreeSql/Internal/CommonExpression.cs | 63 +- .../ClickHouseExpression.cs | 13 + .../MySql/CustomMySqlExpression.cs | 12 + .../Oracle/CustomOracleExpression.cs | 13 + .../SqlServer/CustomSqlServerExpression.cs | 13 + .../DamengExpression.cs | 13 + .../FirebirdExpression.cs | 13 + .../FreeSql.Provider.GBase/GBaseExpression.cs | 13 + .../MsAccessExpression.cs | 12 + .../FreeSql.Provider.MySql/MySqlExpression.cs | 12 + .../MySql/OdbcMySqlExpression.cs | 12 + .../Oracle/OdbcOracleExpression.cs | 13 + .../SqlServer/OdbcSqlServerExpression.cs | 13 + .../OracleExpression.cs | 13 + .../QuestDbExpression.cs | 13 +- .../ShenTongExpression.cs | 14 +- .../SqlServerExpression.cs | 13 + .../SqliteExpression.cs | 10 + .../FreeSql.Provider.Xugu/XuguExpression.cs | 15 +- 20 files changed, 751 insertions(+), 772 deletions(-) diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index d81cee4b2..91534b2e5 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2088,85 +2088,71 @@ - + - 命令超时设置(秒) - - - - - - - 审核或跟踪 ToList 即将返回的数据 - - - - - - - 执行SQL查询,返回 DataTable + 将查询转为删除对象,以便支持导航对象或其他查询功能删除数据,如下: + fsql.Select<T1>().Where(a => a.Options.xxx == 1).ToDelete().ExecuteAffrows() + 注意:此方法不是将数据查询到内存循环删除,上面的代码产生如下 SQL 执行: + DELETE FROM `T1` WHERE id in (select a.id from T1 a left join Options b on b.t1id = a.id where b.xxx = 1) + 复杂删除使用该方案的好处: + 1、删除前可预览测试数据,防止错误删除操作; + 2、支持更加复杂的删除操作(IDelete 默认只支持简单的操作); - + - 执行SQL查询,返回 properties 指定的实体类属性,并以 DataTable 接收 - - 属性名:Name导航属性:Parent.Name多表:b.Name - - - - - 以字典的形式返回查询结果 - 注意:字典的特点会导致返回的数据无序 - - - - - - - - 执行SQL查询,返回 T1 实体所有字段的记录,记录不存在时返回 Count 为 0 的列表 - 注意: - 1、ToList(a => a) 可以返回 a 所有实体 - 2、ToList(a => new { a }) 这样也可以 - 3、ToList((a, b, c) => new { a, b, c }) 这样也可以 - 4、abc 怎么来的?请试试 fsql.Select<T1, T2, T3>() + 将查询转为更新对象,以便支持导航对象或其他查询功能更新数据,如下: + fsql.Select<T1>().Where(a => a.Options.xxx == 1).ToUpdate().Set(a => a.Title, "111").ExecuteAffrows() + 注意:此方法不是将数据查询到内存循环更新,上面的代码产生如下 SQL 执行: + UPDATE `T1` SET Title = '111' WHERE id in (select a.id from T1 a left join Options b on b.t1id = a.id where b.xxx = 1) + 复杂更新使用该方案的好处: + 1、更新前可预览测试数据,防止错误更新操作; + 2、支持更加复杂的更新操作(IUpdate 默认只支持简单的操作); - + - 执行SQL查询,返回 T1 实体、以及 LeftJoin/InnerJoin/RightJoin 对象 + 设置表名规则,可用于分库/分表,参数1:实体类型;参数2:默认表名;返回值:新表名; + 设置多次,可查询分表后的多个子表记录,以 UNION ALL 形式执行。 + 如:select.AsTable((type, oldname) => "table_1").AsTable((type, oldname) => "table_2").AsTable((type, oldname) => "table_3").ToSql(a => a.Id); + select * from (SELECT a."Id" as1 FROM "table_1" a) ftb + UNION ALL select * from (SELECT a."Id" as1 FROM "table_2" a) ftb + UNION ALL select * from (SELECT a."Id" as1 FROM "table_3" a) ftb + 还可以这样:select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList() - false: 返回 2级 LeftJoin/InnerJoin/RightJoin 对象;true: 返回所有 LeftJoin/InnerJoin/RightJoin 的导航数据 + - + - 执行SQL查询,分块返回数据,可减少内存开销。比如读取10万条数据,每次返回100条处理。 + 设置别名规则,可用于拦截表别名,实现类似 sqlserver 的 with(nolock) 需求 + 如:select.AsAlias((_, old) => $"{old} with(lock)") - 数据块的大小 - 处理数据块 - false: 返回 2级 LeftJoin/InnerJoin/RightJoin 对象;true: 返回所有 LeftJoin/InnerJoin/RightJoin 的导航数据 - - - - 执行SQL查询,返回 field 指定字段的记录,并以元组或基础类型(int,string,long)接收,记录不存在时返回 Count 为 0 的列表 - - - + - + - 执行SQL查询,返回 T1 实体所有字段的第一条记录,记录不存在时返回 null + 动态Type,在使用 Select<object> 后使用本方法,指定实体类型 + + + + + + + 返回即将执行的SQL语句 + + 指定字段 + + + + + 执行SQL查询,是否有记录 - - - 执行SQL查询,返回 T1 实体所有字段的第 查询的记录数量 @@ -2813,87 +2799,6 @@ - - - 按聚合条件过滤,Having(a => a.Count() > 10) - - lambda表达式 - new TNavigate { Title = a.Title }) - - 即能 ThenInclude,还可以二次过滤(这个 EFCore 做不到?) - - - - - 按属性名字符串进行 Include/IncludeMany 操作 - - - - - - - 按属性名字符串进行 Include/IncludeMany 操作 - - true 时生效 - - - - - - 实现 select .. from ( select ... from t ) a 这样的功能 - 使用 AsTable 方法也可以达到效果 - 示例:WithSql("select * from id=@id", new { id = 1 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - SQL语句 - 参数 - - - - - 实现 select .. from ( select .. UNION ALL select .. ) a 这样的功能(基于内存数据) - - 内存数据 - - - - - 嵌套查询 select * from ( select ... from table ... ) a - - - - - - - - 查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com") - - lambda表达式 - - - - - 查询条件,Where(true, a => a.Id > 10),支导航对象查询,Where(true, a => a.Author.Email == "2881099@qq.com") - - true 时生效 - lambda表达式 - - - - - 按列排序,OrderBy(a => a.Time) - - - - - - - - 按列倒向排序,OrderByDescending(a => a.Time) - - 列 - - 按聚合条件过滤,Having(a => a.Count() > 10) @@ -3384,13 +3289,6 @@ - - - 执行SQL语句,返回更新后的记录 - 注意:此方法只有 Postgresql/SqlServer 有效果 - - - 指定事务对象 @@ -3486,91 +3384,108 @@ - 禁用全局过滤功能,不传参【主库】 + 禁用全局过滤功能,不传参数时将禁用所有 - - - - + 零个或多个过滤器名字 + - + - 查询,ExecuteReader(dr => {}, "select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> + 设置表名 - - - + + + - + - 查询 + 返回即将执行的SQL语句 - - - + - + - 查询,ExecuteArray("select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> + 执行SQL语句,返回影响的行数 + + + + + + 主库连接池 + + + + + 从库连接池 + + + + + 数据库类型 + + + + + UseConnectionString 时候的值 + + + + + UseSalve 时候的值 + + + + + 唯一标识 + + + + + 开启事务(不支持异步) + + 事务体 () => {} + + + + 开启事务(不支持异步) + + + 事务体 () => {} + + + + 当前线程的事务 + + + + + 将 new { id = 1 } 或者 Dictionary<string, object> 转换为 DbParameter[] + + new { id = 1 } 或者 Dictionary<string, object> + + + + + SQL 命令执行类,fsql.Ado.CommandFluent("select * from user where age > @age", new { age = 25 }) + .WithConnection(connection) + .WithTransaction(transaction) + .WithParameter("age", 25) + .WithParameter("id", 11) + .CommandType(CommandType.Text) + .CommandTimeout(60) + .Query<T>(); 或者 ExecuteNonQuery/ExecuteScalar/ExecuteDataTable/ExecuteDataSet/ExecuteArray - + - 查询 + 测试数据库是否连接正确,本方法执行如下命令: + MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1 + Oracle: SELECT 1 FROM dual - - - - - - - 查询,ExecuteDataSet("select * from user where age > @age; select 2", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - 查询 - - - - - - - - 查询,ExecuteDataTable("select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - 在【主库】执行 - - - - - - - - 在【主库】执行,ExecuteNonQuery("delete from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - 命令超时设置(秒) + 命令超时设置(秒) true: 成功, false: 失败 @@ -3718,177 +3633,6 @@ - - - 测试数据库是否连接正确,本方法执行如下命令: - MySql/SqlServer/PostgreSQL/达梦/人大金仓/神通: SELECT 1 - Oracle: SELECT 1 FROM dual - - 命令超时设置(秒) - - true: 成功, false: 失败 - - - - 查询,若使用读写分离,查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】 - - - - - - - - - - 查询,ExecuteReaderAsync(dr => {}, "select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 查询 - - - - - - - - - 查询,ExecuteArrayAsync("select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 查询 - - - - - - - - - 查询,ExecuteDataSetAsync("select * from user where age > @age; select 2", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 查询 - - - - - - - - - 查询,ExecuteDataTableAsync("select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 在【主库】执行 - - - - - - - - - 在【主库】执行,ExecuteNonQueryAsync("delete from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 在【主库】执行 - - - - - - - - - 在【主库】执行,ExecuteScalarAsync("select 1 from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new SqlParameter { ParameterName = "age", Value = 25 }) - - - - - - - - - - - 执行SQL返回对象集合,QueryAsync<User>("select * from user where age > @age", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - - - 执行SQL返回对象集合,Query<User>("select * from user where age > @age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 }) - - - - - - - - - - - - 执行SQL返回对象集合,Query<User, Address>("select * from user where age > @age; select * from address", new { age = 25 }) - 提示:parms 参数还可以传 Dictionary<string, object> - - - - - - - - 可自定义解析表达式 @@ -3977,7 +3721,360 @@ 实体配置 - t.GetTablesByDatabase(System.String[])"> + + + + + 索引配置 + + + + + 实体类型 + + + + + 实体的属性 + + + + + 实体的属性配置 + + + + + 标识符,可将 CurdBefore 与 CurdAfter 进行匹配 + + + + + 操作类型 + + + + + 实体类型 + + + + + 实体类型的元数据 + + + + + 执行的 SQL + + + + + 参数化命令 + + + + + 状态数据,可与 CurdAfter 共享 + + + + + 发生的错误 + + + + + 执行SQL命令,返回的结果 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 标识符,可将 SyncStructureBeforeEventArgs 与 SyncStructureAfterEventArgs 进行匹配 + + + + + 实体类型 + + + + + 状态数据,可与 SyncStructureAfter 共享 + + + + + 执行的 SQL + + + + + 发生的错误 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 类型 + + + + + 属性列的元数据 + + + + + 反射的属性信息 + + + + + 获取实体的属性值,也可以设置实体的属性新值 + + + + + 实体对象 + + + + + 中断实体对象审计 + false: 每个实体对象的属性都会审计(默认) + true: 每个实体对象只审计一次 + + + + + ADO.NET 数据流读取对象 + + + + + DataReader 对应的 Index 位置 + + + + + DataReader 对应的 PropertyInfo + + + + + 获取 Index 对应的值,也可以设置拦截的新值 + + + + + 标识符,可将 CommandBefore 与 CommandAfter 进行匹配 + + + + + 状态数据,可与 CommandAfter 共享 + + + + + 发生的错误 + + + + + 执行SQL命令,返回的结果 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 标识符,可将 TraceBeforeEventArgs 与 TraceAfterEventArgs 进行匹配 + + + + + 状态数据,可与 TraceAfter 共享 + + + + + 备注 + + + + + 发生的错误 + + + + + 耗时(单位:Ticks) + + + + + 耗时(单位:毫秒) + + + + + 【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改 + + + + + 转小写同步结构,适用 PostgreSQL + + + + + 转大写同步结构,适用 Oracle/达梦/人大金仓 + + + + + 将数据库的主键、自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。 + 本功能会影响 IFreeSql 首次访问的速度。 + 若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除 + + + + + 不使用命令参数化执行,针对 Insert/Update + + + + + 是否生成命令参数化执行,针对 lambda 表达式解析 + 注意:常量不会参数化,变量才会做参数化 + var id = 100; + fsql.Select<T>().Where(a => a.id == id) 会参数化 + fsql.Select<T>().Where(a => a.id == 100) 不会参数化 + + + + + 延时加载导航属性对象,导航属性需要声明 virtual + + + + + 将实体类型与数据库对比,返回DDL语句 + + + + + + + 将实体类型集合与数据库对比,返回DDL语句 + + 实体类型 + + + + + 将实体类型与数据库对比,返回DDL语句(指定表名) + + 实体类型 + 指定表名对比 + + + + + 同步实体类型到数据库 + 注意:生产环境中谨慎使用 + + + + + + 同步实体类型集合到数据库 + 注意:生产环境中谨慎使用 + + + + + + 同步实体类型到数据库(指定表名) + 注意:生产环境中谨慎使用 + + 实体类型 + 指定表名对比 + 强制同步结构,无视缓存每次都同步 + + + + 根据 System.Type 获取数据库信息 + + + + + + + FreeSql FluentApi 配置实体,方法名与特性相同 + + + + + + + + FreeSql FluentApi 配置实体,方法名与特性相同 + + + + + + + + 获取 FreeSql FluentApi 配置实体的元数据 + + + 未使用ConfigEntity配置时,返回null + + + + 获取实体类核心配置 + + + + + + + 获取所有数据库 + + + + 获取指定数据库的表信息,包括表、列详情、主键、唯一键、索引、外键、备注 @@ -4347,329 +4444,6 @@ 多表:b.Name - summary> - - - - - - 获取c#类型对象 - - - - - - - 获取ado.net读取方法, GetBoolean、GetInt64 - - - - - - - 序列化 - - - - - - - 反序列化 - - - - - - - 获取数据库枚举类型,适用 PostgreSQL - - - - - - - 临时 LambdaExpression.Parameter - - - - - 如果实体类有自增属性,分成两个 List,有值的Item1 merge,无值的Item2 insert - - - - - - - AsType, Ctor, ClearData 三处地方需要重新加载 - - - - - AsType, Ctor, ClearData 三处地方需要重新加载 - - - - - 动态读取 DescriptionAttribute 注释文本 - - - - - - - 通过属性的注释文本,通过 xml 读取 - - - Dict:key=属性名,value=注释 - - - - 更新实体的元数据 - - - - - 执行更新的 SQL - - - - - 执行更新命令的参数 - - - - - 执行更新命令影响的行 - - - - - 更新的实体数量 - - - - - 更新的实体 - - - - - 映射优先级,默认: Attribute > FluentApi > Aop - - - - - 实体特性 - [Table(Name = "tabname")] - [Column(Name = "table_id")] - - - - - 流式接口 - fsql.CodeFirst.ConfigEntity(a => a.Name("tabname")) - fsql.CodeFirst.ConfigEntity(a => a.Property(b => b.Id).Name("table_id")) - - - - - AOP 特性 https://github.com/dotnetcore/FreeSql/wiki/AOP - fsql.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = "public.tabname"; - fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = "table_id"; - - - - - 不进行任何处理 - - - - - 将帕斯卡命名字符串转换为下划线分隔字符串 - - BigApple -> Big_Apple - - - - - 将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写 - - BigApple -> BIG_APPLE - - - - - 将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写 - - BigApple -> big_apple - - - - - 将字符串转换为大写 - - BigApple -> BIGAPPLE - - - - - 将字符串转换为小写 - - BigApple -> bigapple - - - - - 创建一个过滤器 - 提示:在 Lambda 中判断登陆身份,请参考资料 AsyncLocal - - - 名字 - 表达式 - 条件在最前面 - - - - - 创建一个动态过滤器,当 condition 返回值为 true 时才生效 - 场景:当登陆身份是管理员,则过滤条件不生效 - 提示:在 Lambda 中判断登陆身份,请参考资料 AsyncLocal - - - 名字 - 委托,返回值为 true 时才生效 - 表达式 - 条件在最前面 - - - - - 创建一个过滤器(实体类型 属于指定 TEntity 才会生效) - 提示:在 Lambda 中判断登陆身份,请参考资料 AsyncLocal - - - 名字 - 表达式 - 条件在最前面 - - - - - 创建一个过滤器(实体类型 属于指定 TEntity 才会生效) - 场景:当登陆身份是管理员,则过滤条件不生效 - 提示:在 Lambda 中判断登陆身份,请参考资料 AsyncLocal - - - 名字 - 委托,返回值为 true 时才生效 - 表达式 - 条件在最前面 - - - - - 使用指定 DbConnection 连接执行 - - - - - - - 使用指定 DbTransaction 事务执行 - - - - - - - 增加参数化对象 - - 参数名 - 参数值 - 修改本次创建好的参数化对象,比如将 parameterName 参数修改为 Output 类型 - - - - - 设置执行的命令类型,SQL文本、或存储过程 - - - - - - - 设置命令执行超时(秒) - - - - - - - 分页信息 - - - - - 第几页,从1开始 - - - - - 每页多少 - - - - - 查询的记录数量 - - - - - 当前操作的数据 - - - - - 当前批次 - - - - - 总批次数量 - - - - - 获取 obj.CsName 属性值 MapType 之后的数据库值 - - - - - - - 获取 obj.CsName 属性原始值(不经过 MapType) - - - - - - 设置 obj.CsName 属性值 - - - - - - - 动态过滤条件 - - - - - 属性名:Name - 导航属性:Parent.Name - 多表:b.Name - - 操作符 @@ -4858,12 +4632,6 @@ 超时 - - - 获取资源 - - - 使用完毕后,归还资源 @@ -4939,12 +4707,6 @@ 资源对象 - - - 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象 - - 资源对象 - 归还对象给对象池的时候触发 @@ -5858,28 +5620,6 @@ 对象池 - - - 动态构建Class Type - - - - - - 根据字典,创建 table 对应的实体对象 - - - - - - - - 根据实体对象,创建 table 对应的字典 - - - - - C#: that >= between && that <= and diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 5a09053a7..1928d8b67 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1902,32 +1902,46 @@ namespace FreeSql.Internal case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, tsc); break; case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, tsc); break; case "System.TimeSpan": - if (exp4.Expression != null && ( - // 如果是以 TimeSpan.Subtract(DateTime) 的方式调用的 - (exp4.Expression.NodeType == ExpressionType.Call && - exp4.Expression is MethodCallExpression exp4CallExp && - exp4CallExp.Method.Name == "Subtract" && - exp4CallExp.Object != null && exp4CallExp.Object.Type == typeof(DateTime) && - exp4CallExp.Arguments.Count == 1 && exp4CallExp.Arguments[0].Type == typeof(DateTime)) - // 如果是以 TimeSpan1 -/+ TimeSpan2 的方式调用的 - || (exp4.Expression.NodeType == ExpressionType.Subtract || exp4.Expression.NodeType == ExpressionType.Add) - ) - ) + if (exp4.Expression != null) { - var left = ExpressionLambdaToSql(exp4.Expression, tsc); - switch (exp4.Member.Name) + var exp4MemberIsTrue = false; + // 如果是以 DateTime.Subtract(DateTime) 的方式调用的 + if (exp4.Expression.NodeType == ExpressionType.Call && + exp4.Expression is MethodCallExpression exp4CallExp && + exp4CallExp.Method.Name == "Subtract" && + exp4CallExp.Object != null && exp4CallExp.Object.Type == typeof(DateTime) && + exp4CallExp.Arguments.Count == 1 && exp4CallExp.Arguments[0].Type == typeof(DateTime)) { - case "Days": return $"floor(({left})/{60 * 60 * 24})"; - case "Hours": return $"floor(({left})/{60 * 60}%24)"; - case "Milliseconds": return $"(({left})*1000)"; - case "Minutes": return $"floor(({left})/60%60)"; - case "Seconds": return $"(({left})%60)"; - case "Ticks": return $"(({left})*10000000)"; - case "TotalDays": return $"(({left})/{60 * 60 * 24}.0)"; - case "TotalHours": return $"(({left})/{60 * 60}.0)"; - case "TotalMilliseconds": return $"(({left})*1000)"; - case "TotalMinutes": return $"(({left})/60.0)"; - case "TotalSeconds": return $"({left})"; + extRet = ExpressionLambdaToSqlCallDateDiff(exp4.Member.Name, exp4CallExp.Object, exp4CallExp.Arguments[0], tsc); + if (string.IsNullOrEmpty(extRet) == false) return extRet; + exp4MemberIsTrue = true; + } + // 如果是以 DateTime1 - DateTime2 的方式调用的 + else if (exp4.Expression.NodeType == ExpressionType.Subtract && exp4.Expression.Type == typeof(TimeSpan) && + exp4.Expression is BinaryExpression exp4BinaryExp && + exp4BinaryExp.Left.Type == typeof(DateTime) && exp4BinaryExp.Right.Type == typeof(DateTime)) + { + extRet = ExpressionLambdaToSqlCallDateDiff(exp4.Member.Name, exp4BinaryExp.Left, exp4BinaryExp.Right, tsc); + if (string.IsNullOrEmpty(extRet) == false) return extRet; + exp4MemberIsTrue = true; + } + if (exp4MemberIsTrue) + { + var left = ExpressionLambdaToSql(exp4.Expression, tsc); + switch (exp4.Member.Name) + { + case "Days": return $"floor(({left})/{60 * 60 * 24})"; + case "Hours": return $"floor(({left})/{60 * 60}%24)"; + case "Milliseconds": return $"(({left})*1000)"; + case "Minutes": return $"floor(({left})/60%60)"; + case "Seconds": return $"(({left})%60)"; + case "Ticks": return $"(({left})*10000000)"; + case "TotalDays": return $"(({left})/{60 * 60 * 24}.0)"; + case "TotalHours": return $"(({left})/{60 * 60}.0)"; + case "TotalMilliseconds": return $"(({left})*1000)"; + case "TotalMinutes": return $"(({left})/60.0)"; + case "TotalSeconds": return $"({left})"; + } } } throw new Exception(CoreErrorStrings.Unable_Parse_Expression(exp4)); @@ -2398,6 +2412,7 @@ namespace FreeSql.Internal public abstract string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc); + public virtual string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) { return null; } public abstract string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc); diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs index 0938d2b1e..02abd4036 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs @@ -421,6 +421,19 @@ namespace FreeSql.ClickHouse } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"dateDiff(day,{getExp(date2)},toDateTime({getExp(date1)}))"; + case "TotalHours": return $"dateDiff(hour,{getExp(date2)},toDateTime({getExp(date1)}))"; + case "TotalMilliseconds": return $"dateDiff(millisecond, {getExp(date2)},toDateTime({getExp(date1)}))"; + case "TotalMinutes": return $"dateDiff(minute,{getExp(date2)},toDateTime({getExp(date1)}))"; + case "TotalSeconds": return $"dateDiff(second,{getExp(date2)},toDateTime({getExp(date1)}))"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlExpression.cs b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlExpression.cs index 7076d9710..783b7464c 100644 --- a/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlExpression.cs +++ b/Providers/FreeSql.Provider.Custom/MySql/CustomMySqlExpression.cs @@ -379,6 +379,18 @@ namespace FreeSql.Custom.MySql } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"timestampdiff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"timestampdiff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"timestampdiff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"timestampdiff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleExpression.cs b/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleExpression.cs index 603f8944e..4a473cd1c 100644 --- a/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleExpression.cs +++ b/Providers/FreeSql.Provider.Custom/Oracle/CustomOracleExpression.cs @@ -384,6 +384,19 @@ namespace FreeSql.Custom.Oracle } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"(({getExp(date1)}+0)-({getExp(date2)}+0))"; + case "TotalHours": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*24)"; + case "TotalMilliseconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60 * 1000})"; + case "TotalMinutes": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60})"; + case "TotalSeconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerExpression.cs b/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerExpression.cs index 97e829e86..ab1318707 100644 --- a/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Custom/SqlServer/CustomSqlServerExpression.cs @@ -381,6 +381,19 @@ namespace FreeSql.Custom.SqlServer } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMilliseconds": return $"datediff(millisecond,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Dameng/DamengExpression.cs b/Providers/FreeSql.Provider.Dameng/DamengExpression.cs index f4b6c444b..23ed1cedd 100644 --- a/Providers/FreeSql.Provider.Dameng/DamengExpression.cs +++ b/Providers/FreeSql.Provider.Dameng/DamengExpression.cs @@ -384,6 +384,19 @@ namespace FreeSql.Dameng } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"(cast({getExp(date1)} as timestamp with time zone)-{getExp(date2)})"; + case "TotalHours": return $"((cast({getExp(date1)} as timestamp with time zone)-{getExp(date2)})*24)"; + case "TotalMilliseconds": return $"((cast({getExp(date1)} as timestamp with time zone)-{getExp(date2)})*{24 * 60 * 60 * 1000})"; + case "TotalMinutes": return $"((cast({getExp(date1)} as timestamp with time zone)-{getExp(date2)})*{24 * 60})"; + case "TotalSeconds": return $"((cast({getExp(date1)} as timestamp with time zone)-{getExp(date2)})*{24 * 60 * 60})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs b/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs index 17a86f775..4c72b727b 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs @@ -369,6 +369,19 @@ namespace FreeSql.Firebird } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff(day from {getExp(date2)} to {getExp(date1)})"; + case "TotalHours": return $"datediff(hour from {getExp(date2)} to {getExp(date1)})"; + case "TotalMilliseconds": return $"datediff(millisecond from {getExp(date2)} to {getExp(date1)})"; + case "TotalMinutes": return $"datediff(minute from {getExp(date2)} to {getExp(date1)})"; + case "TotalSeconds": return $"datediff(second from {getExp(date2)} to {getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.GBase/GBaseExpression.cs b/Providers/FreeSql.Provider.GBase/GBaseExpression.cs index 8a77e2524..477fbff33 100644 --- a/Providers/FreeSql.Provider.GBase/GBaseExpression.cs +++ b/Providers/FreeSql.Provider.GBase/GBaseExpression.cs @@ -369,6 +369,19 @@ namespace FreeSql.GBase } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"({getExp(date1)}-{getExp(date2)})"; + case "TotalHours": return $"(({getExp(date1)}-{getExp(date2)})*24)"; + case "TotalMilliseconds": return $"(({getExp(date1)}-{getExp(date2)})*{24 * 60 * 60 * 1000})"; + case "TotalMinutes": return $"(({getExp(date1)}-{getExp(date2)})*{24 * 60})"; + case "TotalSeconds": return $"(({getExp(date1)}-{getExp(date2)})*{24 * 60 * 60})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.MsAccess/MsAccessExpression.cs b/Providers/FreeSql.Provider.MsAccess/MsAccessExpression.cs index ec66c329a..99cb023c0 100644 --- a/Providers/FreeSql.Provider.MsAccess/MsAccessExpression.cs +++ b/Providers/FreeSql.Provider.MsAccess/MsAccessExpression.cs @@ -321,6 +321,18 @@ namespace FreeSql.MsAccess } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff('d',{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff('h',{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff('n',{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff('s',{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs index c92eb7206..368f9ef94 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs @@ -381,6 +381,18 @@ namespace FreeSql.MySql } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"timestampdiff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"timestampdiff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"timestampdiff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"timestampdiff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs index 063f548b3..789a56c24 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs @@ -379,6 +379,18 @@ namespace FreeSql.Odbc.MySql } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"timestampdiff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"timestampdiff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"timestampdiff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"timestampdiff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs index bd6a1c9c7..1a7c87043 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleExpression.cs @@ -384,6 +384,19 @@ namespace FreeSql.Odbc.Oracle } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"(({getExp(date1)}+0)-({getExp(date2)}+0))"; + case "TotalHours": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*24)"; + case "TotalMilliseconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60 * 1000})"; + case "TotalMinutes": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60})"; + case "TotalSeconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index 073a377f0..14a19833e 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -381,6 +381,19 @@ namespace FreeSql.Odbc.SqlServer } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMilliseconds": return $"datediff(millisecond,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs index 827e794b6..664e74099 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleExpression.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleExpression.cs @@ -384,6 +384,19 @@ namespace FreeSql.Oracle } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"(({getExp(date1)}+0)-({getExp(date2)}+0))"; + case "TotalHours": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*24)"; + case "TotalMilliseconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60 * 1000})"; + case "TotalMinutes": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60})"; + case "TotalSeconds": return $"((({getExp(date1)}+0)-({getExp(date2)}+0))*{24 * 60 * 60})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.QuestDb/QuestDbExpression.cs b/Providers/FreeSql.Provider.QuestDb/QuestDbExpression.cs index cbd1e2a8c..7a0851f62 100644 --- a/Providers/FreeSql.Provider.QuestDb/QuestDbExpression.cs +++ b/Providers/FreeSql.Provider.QuestDb/QuestDbExpression.cs @@ -420,7 +420,18 @@ namespace FreeSql.QuestDb return null; } - + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff('d',{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff('h',{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff('m',{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff('s',{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs b/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs index f256dbc63..07823f95d 100644 --- a/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs +++ b/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs @@ -428,6 +428,18 @@ namespace FreeSql.ShenTong } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff('day',{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff('hour',{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff('minute',{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff('second',{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); @@ -460,7 +472,7 @@ namespace FreeSql.ShenTong case "AddMilliseconds": return $"dateadd('second',({args1})/1000,{left})"; case "AddMinutes": return $"dateadd('minute',{args1},{left})"; case "AddMonths": return $"dateadd('month',{args1},{left})"; - case "AddSeconds": return $"dateadd('second', {args1}, {left})"; + case "AddSeconds": return $"dateadd('second',{args1},{left})"; case "AddTicks": return $"dateadd('second',({args1})/10000000,{left})"; case "AddYears": return $"dateadd('year',{args1},{left})"; case "Subtract": diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index c7ce2a3cf..4afc463fa 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -380,6 +380,19 @@ namespace FreeSql.SqlServer } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMilliseconds": return $"datediff(millisecond,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs index 13ce403c7..b864b33ff 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs @@ -396,6 +396,16 @@ namespace FreeSql.Sqlite } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"(strftime('%d',{getExp(date1)})-strftime('%d',{getExp(date2)}))"; + case "TotalHours": return $"(strftime('%h',{getExp(date1)})-strftime('%h',{getExp(date2)}))"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); diff --git a/Providers/FreeSql.Provider.Xugu/XuguExpression.cs b/Providers/FreeSql.Provider.Xugu/XuguExpression.cs index 71773e541..dfc1b58ea 100644 --- a/Providers/FreeSql.Provider.Xugu/XuguExpression.cs +++ b/Providers/FreeSql.Provider.Xugu/XuguExpression.cs @@ -429,6 +429,19 @@ namespace FreeSql.Xugu } return null; } + public override string ExpressionLambdaToSqlCallDateDiff(string memberName, Expression date1, Expression date2, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (memberName) + { + case "TotalDays": return $"datediff(day,{getExp(date2)},{getExp(date1)})"; + case "TotalHours": return $"datediff(hour,{getExp(date2)},{getExp(date1)})"; + case "TotalMilliseconds": return $"datediff(millisecond,{getExp(date2)},{getExp(date1)})"; + case "TotalMinutes": return $"datediff(minute,{getExp(date2)},{getExp(date1)})"; + case "TotalSeconds": return $"datediff(second,{getExp(date2)},{getExp(date1)})"; + } + return null; + } public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) { Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); @@ -467,7 +480,7 @@ namespace FreeSql.Xugu case "Subtract": switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GetGenericArguments().FirstOrDefault() : exp.Arguments[0].Type).FullName) { - case "System.DateTime": return $"datediff(second, {args1}, {left})"; + case "System.DateTime": return $"datediff(second,{args1},{left})"; } break; case "Equals": return $"({left} = {args1})";