diff --git a/FreeSql.Tests/FreeSql.Tests/Internal/CommonExpressionTest.cs b/FreeSql.Tests/FreeSql.Tests/Internal/CommonExpressionTest.cs index dae1c1bdc..6c9b99df3 100644 --- a/FreeSql.Tests/FreeSql.Tests/Internal/CommonExpressionTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Internal/CommonExpressionTest.cs @@ -4,7 +4,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using FreeSql.DataAnnotations; using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore.Metadata; using Xunit; namespace FreeSql.Tests.Internal @@ -250,6 +252,7 @@ public void IIFTest01() sql = fsql.Select().ToSql(a => a.BoolNullable.Value && a.Id > 0 && a.BoolNullable.Value ? 10 : 11); Assert.Equal(@"SELECT case when a.""BoolNullable"" = 1 AND a.""Id"" > 0 AND a.""BoolNullable"" = 1 then 10 else 11 end as1 FROM ""IIFTest01Model"" a", sql); + } class IIFTest01Model @@ -258,5 +261,68 @@ class IIFTest01Model public bool Bool { get; set; } public bool? BoolNullable { get; set; } } + + [Fact] + public void IIFTest02() + { + var parameters = new List(); + + var fsql = g.sqlite; + var sql = ""; + var startTime = DateTime.UtcNow; + var query = fsql.Select() + .WithParameters(parameters) + .InnerJoin((model1, model2) => + model2.StartDateTime == startTime + && model1.StartTime <= model2.EndDateTime + && model1.StopTime > model2.StartDateTime) + .GroupBy((model1, model2) => new + { + model1.EntityId, + model2.StartDateTime, + model2.EndDateTime, + }) + .WithTempQuery(group => new + { + EntityId = group.Key.EntityId, + DateTime = group.Key.StartDateTime, + TotalRunTime = group.Sum(((group.Value.Item1.StopTime > group.Key.EndDateTime ? group.Key.EndDateTime : group.Value.Item1.StopTime) + - (group.Value.Item1.StartTime < group.Key.StartDateTime ? group.Key.StartDateTime : group.Value.Item1.StartTime)).TotalSeconds), + Count = group.Count() + }) + .WithParameters(parameters); + + sql = query.ToSql(); + Assert.Equal($@"SELECT * +FROM ( + SELECT a.""EntityId"", b.""StartDateTime"" ""DateTime"", sum(((strftime('%s',case when a.""StopTime"" > b.""EndDateTime"" then b.""EndDateTime"" else a.""StopTime"" end)-strftime('%s',case when a.""StartTime"" < b.""StartDateTime"" then b.""StartDateTime"" else a.""StartTime"" end)))) ""TotalRunTime"", count(1) ""Count"" + FROM ""IIFTest02Model1"" a + INNER JOIN ""IIFTest02Model2"" b ON b.""StartDateTime"" = '{startTime.ToString("yyyy-MM-dd HH:mm:ss")}' AND a.""StartTime"" <= b.""EndDateTime"" AND a.""StopTime"" > b.""StartDateTime"" + GROUP BY a.""EntityId"", b.""StartDateTime"", b.""EndDateTime"" ) a", sql); + + } + public class IIFTest02Model1 + { + public long _Id { get; set; } + public long Id { get; set; } + + + public long EntityId { get; set; } + + public DateTime StartTime { get; set; } + public DateTime StopTime { get; set; } + + } + + /// + /// 任务统计日期 + /// + public class IIFTest02Model2 + { + public long Id { get; set; } + public DateTime StartDateTime { get; set; } + public DateTime EndDateTime { get; set; } + + } } } diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 4c12c7fab..5a09053a7 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1902,11 +1902,17 @@ public string ExpressionLambdaToSql(Expression exp, ExpTSC tsc) case "System.String": extRet = ExpressionLambdaToSqlMemberAccessString(exp4, tsc); break; case "System.DateTime": extRet = ExpressionLambdaToSqlMemberAccessDateTime(exp4, tsc); break; case "System.TimeSpan": - if (exp4.Expression != null && exp4.Expression.NodeType == ExpressionType.Call && + 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) + ) + ) { var left = ExpressionLambdaToSql(exp4.Expression, tsc); switch (exp4.Member.Name)