FreeSql icon indicating copy to clipboard operation
FreeSql copied to clipboard

关于自定义表达式函数的建议

Open zhaxg opened this issue 1 year ago • 7 comments

Feature 特性

实现类似linq2db的表达式函数设计模式:
            LinqToDB.Common.Configuration.Linq.AllowMultipleQuery = true;
            LinqToDB.DataProvider.Oracle.OracleTools.UseAlternativeBulkCopy = AlternativeBulkCopy.InsertInto;

            //注册自定义sql函数
            LinqToDB.Linq.Expressions.MapMember<string, string, bool>((a, b) => a.IsGt(b), (x, y) => x.CompareTo(y) > 0);
            LinqToDB.Linq.Expressions.MapMember<string, string, bool>((a, b) => a.IsGe(b), (x, y) => x.CompareTo(y) >= 0);
            LinqToDB.Linq.Expressions.MapMember<string, string, bool>((a, b) => a.IsLt(b), (x, y) => x.CompareTo(y) < 0);
            LinqToDB.Linq.Expressions.MapMember<string, string, bool>((a, b) => a.IsLe(b), (x, y) => x.CompareTo(y) <= 0);
            LinqToDB.Linq.Expressions.MapMember<object, object[], bool>((a, b) => a.IsIn(b), (x, y) => y.Contains(x));
            LinqToDB.Linq.Expressions.MapMember<object, object[], bool>((a, b) => a.IsLooseIn(b), (x, y) => y.Length == 0 || y.Contains(x));

            LinqToDB.Linq.Expressions.MapMember<string, bool>(a => a.IsNullOrEmpty(), a => a == null || a.Length == 0);
            LinqToDB.Linq.Expressions.MapMember<string, bool>(a => a.IsNotNullOrEmpty(), a => a != null && a.Length > 0);
            LinqToDB.Linq.Expressions.MapMember<string, bool>(a => a.IsTrue(), x => new[] { "y", "true", "yes", "1" }.Contains(x.ToLower()));

            LinqToDB.Linq.Expressions.MapMember<IComparable, IComparable, IComparable, bool>((x, low, high) => x.Between(low, high), (x, low, high) => Sql.Between(x, low, high));

简要描述原因

大多数函数都是c#正常使用的函数,不需要再设计一个[ExpressionCall],而且两个静态的扩展函数会冲突

使用场景

// c# code

zhaxg avatar May 23 '24 23:05 zhaxg

两个静态方法冲突是什么意思?

2881099 avatar May 24 '24 06:05 2881099

[ExpressionCall] public static class DbFunc { //必要定义 static + ThreadLocal static ThreadLocal<ExpressionCallContext> context = new ThreadLocal<ExpressionCallContext>();

public static DateTime FormatDateTime(this DateTime that, string arg1) { var up = context.Value; if (up.DataType == FreeSql.DataType.Sqlite) //重写内容 up.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})"; return that; } } 这个方法就是一个很直接的静态扩展方法,没有办法确保不会被团队的人误用了,如果是string.isnullorempty这种,我在正常的逻辑里面可以使用,那么在freesql的查询表达式应该是一致的逻辑,而不是两套逻辑,另外一个isnullorempty扩展方法是特定给freesql去解析sql的

zhaxg avatar May 24 '24 08:05 zhaxg

你可以看看与了解一下linq2db的自定义函数如何实现的

zhaxg avatar May 24 '24 08:05 zhaxg

怎么会被乱用呢,乱用不应该是团队规范的问题么

2881099 avatar May 24 '24 11:05 2881099

扩展方法的命名和表达式函数表示的 SQL 字符串没有啥关联 命名可以有个规范 比如 FormatDateTimeForSqlFun 另外FreeSql经历了这么多版本的迭代肯定不会去修改 自定义解析 的逻辑

d4ilys avatar May 25 '24 08:05 d4ilys

FYI, we at Linq To DB are moving away from mapping one member expression to another expression approach (Expression.Map* APIs) as being troublesome to approach with member builders which convert specific member call/property directly to SQL per-database

MaceWindu avatar Jun 02 '24 15:06 MaceWindu