From 4d8f4ce08d515864f3aa6ebc9e38e6d9dd4e02a2 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Fri, 19 Jan 2024 16:33:15 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20MySql=20AsTreeCte=20?= =?UTF-8?q?=E5=88=AB=E5=90=8D=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 57 ++++++++- FreeSql/Extensions/FreeSqlGlobalExtensions.cs | 9 +- FreeSql/FreeSql.xml | 112 ------------------ .../FreeSql.Provider.Xugu/XuguExpression.cs | 8 +- 4 files changed, 65 insertions(+), 121 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index bcf35301..9019d23b 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -608,10 +608,33 @@ namespace base_entity .UseGenerateCommandParameterWithLambda(true) .Build(); BaseEntity.Initialization(fsql, () => _asyncUow.Value); - #endregion + #endregion + fsql.Delete().Where("1=1").ExecuteAffrows(); + var repoxx = fsql.GetRepository(); + repoxx.DbContextOptions.EnableCascadeSave = true; + repoxx.DbContextOptions.NoneParameter = true; + repoxx.Insert(new VM_District_Child + { + Code = "100000", + Name = "中国", + Childs = new List(new[] { + new VM_District_Child + { + Code = "110000", + Name = "北京", + Childs = new List(new[] { + new VM_District_Child{ Code="110100", Name = "北京市" }, + new VM_District_Child{ Code="110101", Name = "东城区" }, + }) + } + }) + }); + var ttre1 = fsql.Select().Where(a => a.Name == "中国") + .AsTreeCte(pathSelector: a => $"[{a.Name}]{a.Code}", pathSeparator: "=>") + .OrderBy(a => a.Code).ToTreeList(); ; - var list111222 = fsql.Select() + var list111222 = fsql.Select() .InnerJoin((l, p) => l.ProductId == p.ID) .GroupBy((l, p) => new { p.ID, ShopType = l.ShopType ?? 0 }) .WithTempQuery(a => new @@ -3103,3 +3126,33 @@ public partial class Product public string Model { get; set; } } +[Table(Name = "D1_District")] +public class BaseDistrict +{ + [Column(IsPrimary = true, StringLength = 6)] + public string Code { get; set; } + + [Column(StringLength = 20, IsNullable = false)] + public string Name { get; set; } + + [Column(StringLength = 6)] + public virtual string ParentCode { get; set; } + + public int testint { get; set; } +} +[Table(Name = "D1_District")] +public class VM_District_Child : BaseDistrict +{ + public override string ParentCode { get => base.ParentCode; set => base.ParentCode = value; } + + [Navigate(nameof(ParentCode))] + public List Childs { get; set; } +} +[Table(Name = "D1_District")] +public class VM_District_Parent : BaseDistrict +{ + public override string ParentCode { get => base.ParentCode; set => base.ParentCode = value; } + + [Navigate(nameof(ParentCode))] + public VM_District_Parent Parent { get; set; } +} \ No newline at end of file diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index b099ceb2..36f128ea 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -750,17 +750,20 @@ JOIN {select._commonUtils.QuoteSqlName(tbDbName)} a ON cte_tbc.cte_id = a.{selec case DataType.CustomSqlServer: case DataType.Firebird: case DataType.ClickHouse: - sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), select._diymemexpWithTempQuery, null, null); + sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, + Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), select._diymemexpWithTempQuery, null, null); break; case DataType.MySql: case DataType.OdbcMySql: case DataType.CustomMySql: - sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, pathSelector?.Body, select._diymemexpWithTempQuery, null, null); + sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, + Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), select._diymemexpWithTempQuery, null, null); sql1ctePath = $"CAST({sql1ctePath} as char(2000))"; wct2ctePath = sql1ctePath; break; default: - sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, pathSelector?.Body, select._diymemexpWithTempQuery, null, null); + sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, select._tableRule, + Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), select._diymemexpWithTempQuery, null, null); break; } sql1ctePath = $"{sql1ctePath} as cte_path, "; diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 489e88dd..8adf6d85 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -6337,115 +6337,3 @@ -`0})"> - - 插入数据,传入实体集合 - - - - - - - - 插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下: - MySql 5.6+: on duplicate key update - PostgreSQL 9.4+: on conflict do update - SqlServer 2008+: merge into - Oracle 11+: merge into - Sqlite: replace into - 达梦: merge into - 人大金仓:on conflict do update - 神通:merge into - MsAccess:不支持 - 注意区别:FreeSql.Repository 仓储也有 InsertOrUpdate 方法(不依赖数据库特性) - - - - - - - 修改数据 - - - - - - - 修改数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 查询数据 - - - - - - - 查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 删除数据 - - - - - - - 删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 开启事务(不支持异步) - v1.5.0 关闭了线程事务超时自动提交的机制 - - 事务体 () => {} - - - - 开启事务(不支持异步) - v1.5.0 关闭了线程事务超时自动提交的机制 - - - 事务体 () => {} - - - - 数据库访问对象 - - - - - 所有拦截方法都在这里 - - - - - CodeFirst 模式开发相关方法 - - - - - DbFirst 模式开发相关方法 - - - - - 全局过滤设置,可默认附加为 Select/Update/Delete 条件 - - - - diff --git a/Providers/FreeSql.Provider.Xugu/XuguExpression.cs b/Providers/FreeSql.Provider.Xugu/XuguExpression.cs index b6f7c35d..af28b515 100644 --- a/Providers/FreeSql.Provider.Xugu/XuguExpression.cs +++ b/Providers/FreeSql.Provider.Xugu/XuguExpression.cs @@ -105,7 +105,7 @@ namespace FreeSql.Xugu } var value = ExpressionGetValue(callExp.Object, out var success); if (success) return formatSql(value, typeof(string), null, null); - return callExp.Arguments.Count == 0 ? $"cast({getExp(callExp.Object)} as text)" : null; + return callExp.Arguments.Count == 0 ? $"cast({getExp(callExp.Object)} as varchar)" : null; } return null; } @@ -373,10 +373,10 @@ namespace FreeSql.Xugu if (exp.Arguments[1].Type == typeof(bool) || exp.Arguments[1].Type == typeof(StringComparison)) likeOpt = "ILIKE"; } - if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as text) || '%')")}"; - if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || cast({args0Value} as text))")}"; + if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as varchar) || '%')")}"; + if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || cast({args0Value} as varchar))")}"; if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"; - return $"({left}) {likeOpt} ('%' || cast({args0Value} as text) || '%')"; + return $"({left}) {likeOpt} ('%' || cast({args0Value} as varchar) || '%')"; case "ToLower": return $"lower({left})"; case "ToUpper": return $"upper({left})"; case "Substring":