From 72cccffc30fff26f90c0b2df2a9d4aa9b5c95880 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Sun, 14 Jun 2020 10:38:53 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20SqlExt=20=E5=B8=B8?= =?UTF-8?q?=E7=94=A8=E5=BC=80=E7=AA=97=E5=87=BD=E6=95=B0=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/FreeSql.DbContext.xml | 16 +++++ FreeSql.Tests/FreeSql.Tests/UnitTest3.cs | 17 +++++ .../FreeSqlGlobalExpressionCallExtensions.cs | 64 +++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 24 +++++-- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 132d875e..4854f49c 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -125,6 +125,13 @@ 清空状态数据 + + + 根据 lambda 条件删除数据 + + + + 添加 @@ -479,5 +486,14 @@ + + + 批量注入 Repository,可以参考代码自行调整 + + + + + + diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs index 28ea2939..762fdaa9 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs @@ -155,6 +155,23 @@ namespace FreeSql.Tests [Fact] public void Test03() { + var sqlextOver = g.sqlserver.Select() + .InnerJoin((a, b) => b.Id == a.Id) + .ToSql((a, b) => new + { + Id = a.Id, + EdiId = b.Id, + over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue() + }); + var sqlextOverToList = g.sqlserver.Select() + .InnerJoin((a, b) => b.Id == a.Id) + .ToList((a, b) => new + { + Id = a.Id, + EdiId = b.Id, + over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue() + }); + var tttrule = 8; var tttid = new long[] { 18, 19, 4017 }; g.sqlserver.Update().Set(it => it.SongId == (short)(it.SongId & ~tttrule)).Where(it => (it.SongId & tttrule) == tttrule && !tttid.Contains(it.Id)).ExecuteAffrows(); diff --git a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs index 63c48c4e..c8de533c 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExpressionCallExtensions.cs @@ -1,5 +1,6 @@ using FreeSql.DataAnnotations; using System; +using System.Text; using System.Threading; [ExpressionCall] @@ -39,4 +40,67 @@ public static class FreeSqlGlobalExpressionCallExtensions expContext.Value.Result = $"{expContext.Value.ParsedContent["that"]} >= {expContext.Value.ParsedContent["start"]} and {expContext.Value.ParsedContent["that"]} < {expContext.Value.ParsedContent["end"]}"; return false; } +} + +namespace FreeSql +{ + [ExpressionCall] + public static class SqlExt + { + public static ThreadLocal expContext = new ThreadLocal(); + static ThreadLocal expSb = new ThreadLocal(); + static ThreadLocal expSbIsOrderBy = new ThreadLocal(); + + public static ISqlOver Rank() => Over("RANK()"); + public static ISqlOver DenseRank() => Over("DENSE_RANK()"); + public static ISqlOver Count() => Over("COUNT()"); + public static ISqlOver Sum(object column) => Over($"Sum({expContext.Value.ParsedContent["column"]})"); + public static ISqlOver Avg() => Over($"AVG({expContext.Value.ParsedContent["column"]})"); + public static ISqlOver Max(T column) => Over($"MAX({expContext.Value.ParsedContent["column"]})"); + public static ISqlOver Min(T column) => Over($"MIN({expContext.Value.ParsedContent["column"]})"); + public static ISqlOver RowNumber() => Over("ROW_NUMBER()"); + + #region .. over([partition by ..] order by ...) + static ISqlOver Over(string sqlFunc) + { + expSb.Value = new StringBuilder(); + expSbIsOrderBy.Value = false; + expSb.Value.Append($"{sqlFunc} "); + return null; + } + public static ISqlOver Over(this ISqlOver that) + { + expSb.Value.Append("OVER("); + return that; + } + public static ISqlOver PartitionBy(this ISqlOver that, object column) + { + expSb.Value.Append("PARTITION BY ").Append(expContext.Value.ParsedContent["column"]).Append(","); + return that; + } + public static ISqlOver OrderBy(this ISqlOver that, object column) => OrderBy(that, false); + public static ISqlOver OrderByDescending(this ISqlOver that, object column) => OrderBy(that, true); + static ISqlOver OrderBy(this ISqlOver that, bool isDesc) + { + var sb = expSb.Value; + if (expSbIsOrderBy.Value == false) + { + sb.Append("ORDER BY "); + expSbIsOrderBy.Value = true; + } + sb.Append(expContext.Value.ParsedContent["column"]); + if (isDesc) sb.Append(" desc"); + sb.Append(","); + return that; + } + public static TValue ToValue(this ISqlOver that) + { + var sb = expSb.Value.ToString().TrimEnd(','); + expSb.Value.Clear(); + expContext.Value.Result = $"{sb})"; + return default; + } + public interface ISqlOver { } + #endregion + } } \ No newline at end of file diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index c870a2f9..e620643c 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -627,8 +627,11 @@ namespace FreeSql.Internal }; var exp3MethodParams = exp3.Method.GetParameters(); var dbParamsIndex = tsc.dbParams?.Count; - ecc.RawExpression.Add(exp3MethodParams[0].Name, exp3.Arguments[0]); - ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[0], tsc)); + if (exp3MethodParams.Any()) + { + ecc.RawExpression.Add(exp3MethodParams[0].Name, exp3.Arguments[0]); + ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[0], tsc)); + } if (tsc.dbParams?.Count > dbParamsIndex) ecc.DbParameter = tsc.dbParams.Last(); List oldDbParams = tsc.SetDbParamsReturnOld(null); for (var a = 1; a < exp3.Arguments.Count; a++) @@ -646,7 +649,20 @@ namespace FreeSql.Internal { var eccContent = ecc.ParsedContent[exp3MethodParams[a].Name]; if (eccContent == null) - exp3InvokeParams[a] = Expression.Lambda(exp3.Arguments[a]).Compile().DynamicInvoke(); + { + var isdyInvoke = true; + if (exp3.Arguments[a].NodeType == ExpressionType.Call) //判断如果参数也是标记 ExpressionCall + { + var exp3ArgsACallExp = exp3.Arguments[a] as MethodCallExpression; + if (exp3ArgsACallExp.Object == null && ( + _dicTypeExistsExpressionCallAttribute.GetOrAdd(exp3ArgsACallExp.Method.DeclaringType, dttp => dttp.GetCustomAttributes(typeof(ExpressionCallAttribute), true).Any()) || + exp3ArgsACallExp.Method.GetCustomAttributes(typeof(ExpressionCallAttribute), true).Any() + )) + isdyInvoke = false; + } + if (isdyInvoke) + exp3InvokeParams[a] = Expression.Lambda(exp3.Arguments[a]).Compile().DynamicInvoke(); + } else if (exp3.Arguments[a].IsParameter()) exp3InvokeParams[a] = exp3.Arguments[a].Type.CreateInstanceGetDefaultValue(); else @@ -668,7 +684,7 @@ namespace FreeSql.Internal { var sqlRet = exp3.Method.Invoke(null, exp3InvokeParams); if (string.IsNullOrEmpty(ecc.Result) && sqlRet is string) ecc.Result = string.Concat(sqlRet); - if (string.IsNullOrEmpty(ecc.Result)) ecc.Result = ecc.ParsedContent[exp3MethodParams[0].Name]; + if (string.IsNullOrEmpty(ecc.Result) && exp3MethodParams.Any()) ecc.Result = ecc.ParsedContent[exp3MethodParams[0].Name]; if (ecc.UserParameters?.Any() == true) tsc.dbParams?.AddRange(ecc.UserParameters); return ecc.Result; }