From 13cfbf2566da71c44a8c7748df3683fd0d19c680 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Sat, 14 Dec 2024 15:38:55 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20ExpressionTree=20?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=B0=86=20double=20->=20=E8=BD=AC=E6=88=90?= =?UTF-8?q?=20int=20=E7=9A=84=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/Entities/User.cs | 4 + Examples/base_entity/Program.cs | 15 +- Examples/base_entity/base_entity.csproj | 2 +- FreeSql/FreeSql.xml | 415 ++++++++++++------------ FreeSql/Internal/UtilsExpressionTree.cs | 49 ++- 5 files changed, 259 insertions(+), 226 deletions(-) diff --git a/Examples/base_entity/Entities/User.cs b/Examples/base_entity/Entities/User.cs index 58eca3ed7..9b966bdaf 100644 --- a/Examples/base_entity/Entities/User.cs +++ b/Examples/base_entity/Entities/User.cs @@ -1,5 +1,6 @@ using FreeSql; using FreeSql.DataAnnotations; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -76,4 +77,7 @@ public class IdentityTable public int id { get; set; } public string name { get; set; } + + [JsonProperty, Column(DbType = "datetime")] + public DateTime? create_time { get; set; } } \ No newline at end of file diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index ed5d29d38..b2c982c46 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -9,7 +9,6 @@ using FreeSql.Internal.Model; using FreeSql.Odbc.Default; using MessagePack; using Microsoft.Data.SqlClient; -using MySqlConnector; using NetTopologySuite.Geometries; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -577,7 +576,7 @@ namespace base_entity .UseConnectionString(FreeSql.DataType.Firebird, @"database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=5") //.UseQuoteSqlName(false) - //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=3;AllowLoadLocalInfile=true") + .UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;min pool size=1;Max pool size=3;AllowLoadLocalInfile=true") //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true") //.UseAdoConnectionPool(false) @@ -619,6 +618,12 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Insert(new IdentityTable { name = "name01", create_time = DateTime.Now }).ExecuteAffrows(); + var itrt01 = fsql.Select().ToList(); + var itrt02 = fsql.Select().ToList(a => a.create_time); + var itrt03 = fsql.Select().ToList(a => new { a.create_time }); + fsql.CodeFirst.SyncStructure(); @@ -1413,9 +1418,9 @@ var sql11111 = fsql.Select() //}); fsql.Insert(Enumerable.Range(0, 100).Select(a => new User1 { Id = Guid.NewGuid(), Nickname = $"nickname{a}", Username = $"username{a}", Description = $"desc{a}" }).ToArray()).ExecuteAffrows(); - fsql.InsertOrUpdate() - .SetSource(fsql.Select().ToList()) - .ExecuteMySqlBulkCopy(); + //fsql.InsertOrUpdate() + // .SetSource(fsql.Select().ToList()) + // .ExecuteMySqlBulkCopy(); var updatejoin01 = fsql.Update() .Join(fsql.Select(), (a, b) => a.GroupId == b.Id) diff --git a/Examples/base_entity/base_entity.csproj b/Examples/base_entity/base_entity.csproj index a6df2b756..b11396ef7 100644 --- a/Examples/base_entity/base_entity.csproj +++ b/Examples/base_entity/base_entity.csproj @@ -30,7 +30,7 @@ - + diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 4ccbbef74..fd4c68beb 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1087,93 +1087,6 @@ - - - 动态创建实体类型 - - - - - 配置Class - - 类名 - 类标记的特性[Table(Name = "xxx")] [Index(xxxx)] - - - - - 获取类型构建器,可作为要构建的Type来引用 - - - - - 配置属性 - - 属性名称 - 属性类型 - 属性标记的特性-支持多个 - - - - - 配置属性 - - 属性名称 - 属性类型 - 该属性是否重写父类属性 - 属性标记的特性-支持多个 - - - - - 配置属性 - - 属性名称 - 属性类型 - 该属性是否重写父类属性 - 属性默认值 - 属性标记的特性-支持多个 - - - - - 配置父类 - - 父类类型 - - - - - Override属性 - - - - - - Emit动态创建出Class - Type - - - - - - Emit动态创建出Class - Type,不附带获取TableInfo - - - - - - 首字母小写 - - - - - - - 首字母大写 - - - - 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 "" @@ -3150,6 +3063,89 @@ 实体 + + + 更新数据,设置更新的实体集合 + 注意:实体必须定义主键,并且最终会自动附加条件 where id in (source.Id) + + 实体集合 + 根据临时主键更新,a => a.Name | a => new{a.Name,a.Time} | a => new[]{"name","time"} + 忽略 IsVersion 乐观> + + + + + + 联表更新(危险操作) + fsql.Update<T1>() + .Join<T2>((a, b) => a.id == b.id) + .Set((a, b) => a.name == b.name) + .Set((a, b) => a.time == b.time2) + .ExecuteAffrows(); + + + + + + + + 指定事务对象 + + + + + + + 指定事务对象 + + + + + + + 命令超时设置(秒) + + + + + + + 不使用参数化,可通过 IFreeSql.CodeFirst.IsNotCommandParameter 全局性设置 + + 是否不使用参数化 + + + + + 批量执行选项设置,一般不需要使用该方法 + 各数据库 rows, parameters 限制不一样,默认设置: + MySql 500 3000 + PostgreSQL 500 3000 + SqlServer 500 2100 + Oracle 200 999 + Sqlite 200 999 + 若没有事务传入,内部(默认)会自动开启新事务,保证拆包执行的完整性。 + + 指定根据 rows 上限数量拆分执行 + 指定根据 parameters 上限数量拆分执行 + 是否自动开启事务 + + + + + 批量执行时,分批次执行的进度状态 + + 批量执行时的回调委托 + + + + + 更新数据,设置更新的实体 + 注意:实体必须定义主键,并且最终会自动附加条件 where id = source.Id + + 实体 + + 更新数据,设置更新的实体集合 @@ -4292,105 +4288,7 @@ 同步实体类型到数据库(指定表名) 注意:生产环境中谨慎使用 - 实体类型 - 指定表名对比 - 强制同步结构,无视缓存每次都同步 - - - - 根据 System.Type 获取数据库信息 - - - - - - - FreeSql FluentApi 配置实体,方法名与特性相同 - - - - - - - - FreeSql FluentApi 配置实体,方法名与特性相同 - - - - - - - - 获取 FreeSql FluentApi 配置实体的元数据 - - - 未使用ConfigEntity配置时,返回null - - - - 获取实体类核心配置 - - - - - - - 获取所有数据库 - - - - - - 获取指定数据库的表信息,包括表、列详情、主键、唯一键、索引、外键、备注 - - - - - - - 获取指定单表信息,包括列详情、主键、唯一键、索引、备注 - - 表名,如:dbo.table1 - 是否忽略大小写 - - - - - 判断表是否存在 - - 表名,如:dbo.table1 - 是否忽略大小写 - - - - - 获取数据库枚举类型int值 - - - - - - - 获取c#转换,(int)、(long) - - - - - - - 获取c#值 - - - - - - - 获取c#类型,int、long - - - - - + 获取c#类型对象 @@ -5897,28 +5795,6 @@ 对象池 - - - 动态构建Class Type - - - - - - 根据字典,创建 table 对应的实体对象 - - - - - - - - 根据实体对象,创建 table 对应的字典 - - - - - C#: that >= between && that <= and @@ -6485,3 +6361,126 @@ + + + + + 插入数据,传入实体集合 + + + + + + + + 插入数据,传入实体集合 + + + + + + + + 插入或更新数据,此功能依赖数据库特性(低版本可能不支持),参考如下: + 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 + DuckDB: on conflict do update + 达梦: 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/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 1feb67313..ef2d9b667 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -2385,6 +2385,7 @@ namespace FreeSql.Internal Expression tryparseExp = null; Expression tryparseBooleanExp = null; ParameterExpression tryparseVarExp = null; + ParameterExpression tryparseVarExpDecimal = null; switch (type.FullName) { case "System.Guid": @@ -2531,36 +2532,48 @@ namespace FreeSql.Internal break; case "System.Int16": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(short)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(short)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodShortTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } ); break; case "System.Int32": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(int)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(int)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodIntTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } ); break; case "System.Int64": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(long)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(long)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodLongTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } ); @@ -2579,36 +2592,48 @@ namespace FreeSql.Internal break; case "System.UInt16": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(ushort)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(ushort)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodUShortTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } ); break; case "System.UInt32": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(uint)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(uint)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodUIntTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } ); break; case "System.UInt64": tryparseExp = Expression.Block( - new[] { tryparseVarExp = Expression.Variable(typeof(ulong)) }, + new[] { tryparseVarExp = Expression.Variable(typeof(ulong)), tryparseVarExpDecimal = Expression.Variable(typeof(decimal)) }, new Expression[] { Expression.IfThenElse( Expression.IsTrue(Expression.Call(MethodULongTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExp)), Expression.Return(returnTarget, Expression.Convert(tryparseVarExp, typeof(object))), - Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + Expression.IfThenElse( + Expression.IsTrue(Expression.Call(MethodDecimalTryParse, Expression.Convert(valueExp, typeof(string)), Expression.Constant(System.Globalization.NumberStyles.Any), Expression.Constant(null, typeof(IFormatProvider)), tryparseVarExpDecimal)), + Expression.Return(returnTarget, Expression.Convert(Expression.Convert(tryparseVarExpDecimal, tryparseVarExp.Type), typeof(object))), + Expression.Return(returnTarget, Expression.Convert(Expression.Default(typeOrg), typeof(object))) + ) ) } );