From 25984512614bb39c1006923c16b4097960aba0e3 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Fri, 26 Jan 2024 18:59:43 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20Enum=20->=20MapType(st?= =?UTF-8?q?ring)=20+=20GroupBy=20=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B#1727?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SqlServer/MapType/EnumTest.cs | 102 +++++++++------- FreeSql/FreeSql.xml | 112 ++++++++++++++++++ FreeSql/Internal/CommonExpression.cs | 6 +- .../SelectProvider/SelectGroupingProvider.cs | 14 ++- 4 files changed, 185 insertions(+), 49 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/MapType/EnumTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/MapType/EnumTest.cs index 3d657684..25d7be22 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/MapType/EnumTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/MapType/EnumTest.cs @@ -1,6 +1,7 @@ -using FreeSql.DataAnnotations; +using FreeSql.DataAnnotations; using FreeSql.Tests.DataContext.SqlServer; using System; +using System.Linq; using System.Numerics; using Xunit; @@ -31,7 +32,7 @@ namespace FreeSql.Tests.SqlServerMapType [Column(MapType = typeof(int?))] public ToStringMapEnum? enumnullable_to_int { get; set; } } - public enum ToStringMapEnum { й, abc, } + public enum ToStringMapEnum { 中国人, abc, 香港 } [Fact] public void EnumToString() { @@ -39,11 +40,11 @@ namespace FreeSql.Tests.SqlServerMapType var orm = g.sqlserver; var item = new EnumTestMap { }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); - var find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + var find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_string, find.enum_to_string); - Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + Assert.Equal(ToStringMapEnum.中国人, find.enum_to_string); item = new EnumTestMap { enum_to_string = ToStringMapEnum.abc }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); @@ -54,28 +55,28 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); //update all - item.enum_to_string = ToStringMapEnum.; + item.enum_to_string = ToStringMapEnum.香港; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_string, find.enum_to_string); - Assert.Equal(ToStringMapEnum., find.enum_to_string); + Assert.Equal(ToStringMapEnum.香港, find.enum_to_string); - item.enum_to_string = ToStringMapEnum.й; + item.enum_to_string = ToStringMapEnum.中国人; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_string, find.enum_to_string); - Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + Assert.Equal(ToStringMapEnum.中国人, find.enum_to_string); //update set - Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.香港).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); - Assert.Equal(ToStringMapEnum., find.enum_to_string); + Assert.Equal(ToStringMapEnum.香港, find.enum_to_string); Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.abc).ExecuteAffrows()); find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First(); @@ -83,9 +84,18 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(item.id, find.id); Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); + var sql = orm.Select().GroupBy(a => a.id).ToSql(g => new { + id = g.Key, + sum1 = g.Sum(g.Value.enum_to_string == ToStringMapEnum.香港 || g.Value.enum_to_string == ToStringMapEnum.abc ? 1 : 0), + sum2 = g.Sum(g.Value.enum_to_string == ToStringMapEnum.中国人 || g.Value.enum_to_string == ToStringMapEnum.abc ? 1 : 0), + }); + Assert.Equal(@"SELECT a.[id] as1, sum(case when (a.[enum_to_string] = N'香港' OR a.[enum_to_string] = N'abc') then 1 else 0 end) as2, sum(case when (a.[enum_to_string] = N'中国人' OR a.[enum_to_string] = N'abc') then 1 else 0 end) as3 +FROM [EnumTestMap] a +GROUP BY a.[id]", sql); + //delete - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).ExecuteAffrows()); - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.中国人).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.香港).ExecuteAffrows()); Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).ExecuteAffrows()); Assert.Null(orm.Select().Where(a => a.id == item.id).First()); } @@ -102,26 +112,26 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); Assert.Null(find.enumnullable_to_string); - item = new EnumTestMap { enumnullable_to_string = ToStringMapEnum.й }; + item = new EnumTestMap { enumnullable_to_string = ToStringMapEnum.中国人 }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).First(); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); - Assert.Equal(ToStringMapEnum.й, find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum.中国人, find.enumnullable_to_string); //update all - item.enumnullable_to_string = ToStringMapEnum.; + item.enumnullable_to_string = ToStringMapEnum.香港; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First(); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); - Assert.Equal(ToStringMapEnum., find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum.香港, find.enumnullable_to_string); item.enumnullable_to_string = null; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.香港).First()); find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); @@ -144,8 +154,8 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Null(find.enumnullable_to_string); //delete - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).ExecuteAffrows()); - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.中国人).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.香港).ExecuteAffrows()); Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == null).ExecuteAffrows()); Assert.Null(orm.Select().Where(a => a.id == item.id).First()); } @@ -157,11 +167,11 @@ namespace FreeSql.Tests.SqlServerMapType var orm = g.sqlserver; var item = new EnumTestMap { }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); - var find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).First(); + var find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_int, find.enum_to_int); - Assert.Equal(ToStringMapEnum.й, find.enum_to_int); + Assert.Equal(ToStringMapEnum.中国人, find.enum_to_int); item = new EnumTestMap { enum_to_int = ToStringMapEnum.abc }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); @@ -172,28 +182,28 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(ToStringMapEnum.abc, find.enum_to_int); //update all - item.enum_to_int = ToStringMapEnum.; + item.enum_to_int = ToStringMapEnum.香港; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).First(); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_int, find.enum_to_int); - Assert.Equal(ToStringMapEnum., find.enum_to_int); + Assert.Equal(ToStringMapEnum.香港, find.enum_to_int); - item.enum_to_int = ToStringMapEnum.й; + item.enum_to_int = ToStringMapEnum.中国人; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).First(); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enum_to_int, find.enum_to_int); - Assert.Equal(ToStringMapEnum.й, find.enum_to_int); + Assert.Equal(ToStringMapEnum.中国人, find.enum_to_int); //update set - Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).First(); + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.香港).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); - Assert.Equal(ToStringMapEnum., find.enum_to_int); + Assert.Equal(ToStringMapEnum.香港, find.enum_to_int); Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.abc).ExecuteAffrows()); find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).First(); @@ -202,8 +212,8 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(ToStringMapEnum.abc, find.enum_to_int); //delete - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).ExecuteAffrows()); - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.中国人).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.香港).ExecuteAffrows()); Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).ExecuteAffrows()); Assert.Null(orm.Select().Where(a => a.id == item.id).First()); } @@ -220,26 +230,26 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); Assert.Null(find.enumnullable_to_int); - item = new EnumTestMap { enumnullable_to_int = ToStringMapEnum.й }; + item = new EnumTestMap { enumnullable_to_int = ToStringMapEnum.中国人 }; Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.й).First(); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.中国人).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); - Assert.Equal(ToStringMapEnum.й, find.enumnullable_to_int); + Assert.Equal(ToStringMapEnum.中国人, find.enumnullable_to_int); //update all - item.enumnullable_to_int = ToStringMapEnum.; + item.enumnullable_to_int = ToStringMapEnum.香港; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).First(); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.香港).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); - Assert.Equal(ToStringMapEnum., find.enumnullable_to_int); + Assert.Equal(ToStringMapEnum.香港, find.enumnullable_to_int); item.enumnullable_to_int = null; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); - Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).First()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.香港).First()); find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == null).First(); Assert.NotNull(find); Assert.Equal(item.id, find.id); @@ -262,8 +272,8 @@ namespace FreeSql.Tests.SqlServerMapType Assert.Null(find.enumnullable_to_int); //delete - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.й).ExecuteAffrows()); - Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.中国人).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.香港).ExecuteAffrows()); Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == null).ExecuteAffrows()); Assert.Null(orm.Select().Where(a => a.id == item.id).First()); } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 8adf6d85..489e88dd 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -6337,3 +6337,115 @@ +`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/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 5a1c7072..a96230f0 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -25,7 +25,7 @@ namespace FreeSql.Internal public ParameterExpression _lambdaParameter; public ReadAnonymousTypeInfo _map; public string _field; - public ReadAnonymousTypeInfo ParseExpMapResult { get; protected set; } + public ReadAnonymousTypeInfo ParseExpMapResult { get; internal protected set; } public abstract string ParseExp(Expression[] members); } @@ -859,8 +859,10 @@ namespace FreeSql.Internal } Type oldMapType = null; + if (tsc.diymemexp != null) tsc.diymemexp.ParseExpMapResult = null; var left = ExpressionLambdaToSql(leftExp, tsc); - var leftMapColumn = SearchColumnByField(tsc._tables, tsc.currentTable, left); + var leftMapColumn = SearchColumnByField(tsc._tables, tsc.currentTable, left) ?? + (tsc.diymemexp?.ParseExpMapResult?.Table?.ColumnsByCs.TryGetValue(tsc.diymemexp.ParseExpMapResult.CsName, out var dmcol) == true ? dmcol : null); //group by emum -> MapType(string) #1727 var isLeftMapType = leftMapColumn != null && new[] { "AND", "OR", "*", "/", "+", "-" }.Contains(oper) == false && (leftMapColumn.Attribute.MapType != rightExp.Type || leftMapColumn.CsType != rightExp.Type); ColumnInfo rightMapColumn = null; var isRightMapType = false; diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs index 1917cbfe..2d78eda8 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -130,7 +130,19 @@ namespace FreeSql.Internal.CommonProvider return null; } } - return _comonExp.ExpressionLambdaToSql(retExp, new CommonExpression.ExpTSC { _tables = _tables, _tableRule = _select._tableRule, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = true, style = CommonExpression.ExpressionStyle.Where }); + var tsc = new CommonExpression.ExpTSC { _tables = _tables, _tableRule = _select._tableRule, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = true, style = CommonExpression.ExpressionStyle.Where }; + var result = _comonExp.ExpressionLambdaToSql(retExp, tsc); + //ParseExpMapResult = result + if (tsc.mapColumnTmp != null) + ParseExpMapResult = new ReadAnonymousTypeInfo + { + Property = tsc.mapColumnTmp.Table.Properties[tsc.mapColumnTmp.CsName], + CsName = tsc.mapColumnTmp.CsName, + CsType = tsc.mapColumnTmp.CsType, //dtoProp.PropertyType, + MapType = tsc.mapColumnTmp.Attribute.MapType, + Table = tsc.mapColumnTmp.Table + }; + return result; } return null; }