diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 5a71b8ea..35984858 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -11,7 +11,9 @@ using System.Data.Odbc; using System.Data.SqlClient; using System.Data.SQLite; using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; @@ -99,24 +101,53 @@ namespace base_entity public B B { get; set; } } + [Table(Name = "as_table_log_{yyyyMM}", AsTable = "createtime=2022-1-1(1 month)")] + class AsTableLog + { + public Guid id { get; set; } + public string msg { get; set; } + public DateTime createtime { get; set; } + } + + public class SomeEntity + { + [Column(IsIdentity = true)] + public int Id { get; set; } + [Column(MapType = typeof(JToken))] + public Customer Customer { get; set; } + } + + public class Customer // Mapped to a JSON column in the table + { + public string Name { get; set; } + public int Age { get; set; } + public Order[] Orders { get; set; } + } + + public class Order // Part of the JSON column + { + public decimal Price { get; set; } + public string ShippingAddress { get; set; } + } + static void Main(string[] args) { #region 初始化 IFreeSql var fsql = new FreeSql.FreeSqlBuilder() - .UseAutoSyncStructure(true) + //.UseAutoSyncStructure(true) .UseNoneCommandParameter(true) .UseConnectionString(FreeSql.DataType.Sqlite, "data source=test1.db;max pool size=5") - .UseSlave("data source=test1.db", "data source=test2.db", "data source=test3.db", "data source=test4.db") - .UseSlaveWeight(10, 1, 1, 5) + //.UseSlave("data source=test1.db", "data source=test2.db", "data source=test3.db", "data source=test4.db") + //.UseSlaveWeight(10, 1, 1, 5) //.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=2") //.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3") - //.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") - //.UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) + .UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2") + .UseNameConvert(FreeSql.Internal.NameConvertType.ToLower) //.UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=2") //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) @@ -141,6 +172,147 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + fsql.Aop.ParseExpression += (_, e) => + { + //解析 POCO Jsonb a.Customer.Name + if (e.Expression is MemberExpression memExp) + { + var parentMemExps = new Stack(); + parentMemExps.Push(memExp); + while (true) + { + switch (memExp.Expression.NodeType) + { + case ExpressionType.MemberAccess: + memExp = memExp.Expression as MemberExpression; + if (memExp == null) return; + parentMemExps.Push(memExp); + break; + case ExpressionType.Parameter: + var tb = fsql.CodeFirst.GetTableByEntity(memExp.Expression.Type); + if (tb == null) return; + if (tb.ColumnsByCs.TryGetValue(parentMemExps.Pop().Member.Name, out var trycol) == false) return; + if (new[] { typeof(JToken), typeof(JObject), typeof(JArray) }.Contains(trycol.Attribute.MapType.NullableTypeOrThis()) == false) return; + var tmpcol = tb.ColumnsByPosition.OrderBy(a => a.Attribute.Name.Length).First(); + var result = e.FreeParse(Expression.MakeMemberAccess(memExp.Expression, tb.Properties[tmpcol.CsName])); + result = result.Replace(tmpcol.Attribute.Name, trycol.Attribute.Name); + while (parentMemExps.Any()) + { + memExp = parentMemExps.Pop(); + result = $"{result}->>'{memExp.Member.Name}'"; + } + e.Result = result; + return; + } + } + } + }; + + var methodJsonConvertDeserializeObject = typeof(JsonConvert).GetMethod("DeserializeObject", new[] { typeof(string), typeof(Type) }); + var methodJsonConvertSerializeObject = typeof(JsonConvert).GetMethod("SerializeObject", new[] { typeof(object), typeof(JsonSerializerSettings) }); + var jsonConvertSettings = JsonConvert.DefaultSettings?.Invoke() ?? new JsonSerializerSettings(); + FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple[typeof(Customer)] = true; + FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionObjectToStringIfThenElse.Add((LabelTarget returnTarget, Expression valueExp, Expression elseExp, Type type) => + { + return Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(Customer)), + Expression.Return(returnTarget, Expression.Call(methodJsonConvertSerializeObject, Expression.Convert(valueExp, typeof(object)), Expression.Constant(jsonConvertSettings)), typeof(object)), + elseExp); + }); + FreeSql.Internal.Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, Type type) => + { + if (type == typeof(Customer)) return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(methodJsonConvertDeserializeObject, Expression.Convert(valueExp, typeof(string)), Expression.Constant(type)), type)); + return null; + }); + + var seid = fsql.Insert(new SomeEntity + { + Customer = JsonConvert.DeserializeObject(@"{ + ""Age"": 25, + ""Name"": ""Joe"", + ""Orders"": [ + { ""OrderPrice"": 9, ""ShippingAddress"": ""Some address 1"" }, + { ""OrderPrice"": 23, ""ShippingAddress"": ""Some address 2"" } + ] +}") + }).ExecuteIdentity(); + var selist = fsql.Select().ToList(); + + var joes = fsql.Select() + .Where(e => e.Customer.Name == "Joe") + .ToSql(); + + var testitems = new[] + { + new AsTableLog{ msg = "msg01", createtime = DateTime.Parse("2022-1-1 13:00:11") }, + new AsTableLog{ msg = "msg02", createtime = DateTime.Parse("2022-1-2 14:00:12") }, + new AsTableLog{ msg = "msg03", createtime = DateTime.Parse("2022-2-2 15:00:13") }, + new AsTableLog{ msg = "msg04", createtime = DateTime.Parse("2022-2-8 15:00:13") }, + new AsTableLog{ msg = "msg05", createtime = DateTime.Parse("2022-3-8 15:00:13") }, + new AsTableLog{ msg = "msg06", createtime = DateTime.Parse("2022-4-8 15:00:13") }, + new AsTableLog{ msg = "msg07", createtime = DateTime.Parse("2022-6-8 15:00:13") }, + new AsTableLog{ msg = "msg07", createtime = DateTime.Parse("2022-7-1") } + }; + var sqlatb = fsql.Insert(testitems).NoneParameter(); + var sqlat = sqlatb.ToSql(); + var sqlatr = sqlatb.ExecuteAffrows(); + + var sqlatc = fsql.Delete().Where(a => a.id == Guid.NewGuid() && a.createtime.Between(DateTime.Parse("2022-3-1"), DateTime.Parse("2022-5-1"))); + var sqlatca = sqlatc.ToSql(); + var sqlatcr = sqlatc.ExecuteAffrows(); + + var sqlatd1 = fsql.Update().SetSource(testitems[0]); + var sqlatd101 = sqlatd1.ToSql(); + var sqlatd102 = sqlatd1.ExecuteAffrows(); + + var sqlatd2 = fsql.Update().SetSource(testitems[5]); + var sqlatd201 = sqlatd2.ToSql(); + var sqlatd202 = sqlatd2.ExecuteAffrows(); + + var sqlatd3 = fsql.Update().SetSource(testitems); + var sqlatd301 = sqlatd3.ToSql(); + var sqlatd302 = sqlatd3.ExecuteAffrows(); + + var sqlatd4 = fsql.Update(Guid.NewGuid()).Set(a => a.msg == "newmsg"); + var sqlatd401 = sqlatd4.ToSql(); + var sqlatd402 = sqlatd4.ExecuteAffrows(); + + var sqlatd5 = fsql.Update(Guid.NewGuid()).Set(a => a.msg == "newmsg").Where(a => a.createtime.Between(DateTime.Parse("2022-3-1"), DateTime.Parse("2022-5-1"))); + var sqlatd501 = sqlatd5.ToSql(); + var sqlatd502 = sqlatd5.ExecuteAffrows(); + + var sqlatd6 = fsql.Update(Guid.NewGuid()).Set(a => a.msg == "newmsg").Where(a => a.createtime > DateTime.Parse("2022-3-1") && a.createtime < DateTime.Parse("2022-5-1")); + var sqlatd601 = sqlatd6.ToSql(); + var sqlatd602 = sqlatd6.ExecuteAffrows(); + + var sqlatd7 = fsql.Update(Guid.NewGuid()).Set(a => a.msg == "newmsg").Where(a => a.createtime > DateTime.Parse("2022-3-1")); + var sqlatd701 = sqlatd7.ToSql(); + var sqlatd702 = sqlatd7.ExecuteAffrows(); + + var sqlatd8 = fsql.Update(Guid.NewGuid()).Set(a => a.msg == "newmsg").Where(a => a.createtime < DateTime.Parse("2022-5-1")); + var sqlatd801 = sqlatd8.ToSql(); + var sqlatd802 = sqlatd8.ExecuteAffrows(); + + var sqls1 = fsql.Select(); + var sqls101 = sqls1.ToSql(); + var sqls102 = sqls1.ToList(); + + var sqls2 = fsql.Select().Where(a => a.createtime.Between(DateTime.Parse("2022-3-1"), DateTime.Parse("2022-5-1"))); + var sqls201 = sqls2.ToSql(); + var sqls202 = sqls2.ToList(); + + var sqls3 = fsql.Select().Where(a => a.createtime > DateTime.Parse("2022-3-1") && a.createtime < DateTime.Parse("2022-5-1")); + var sqls301 = sqls3.ToSql(); + var sqls302 = sqls3.ToList(); + + var sqls4 = fsql.Select().Where(a => a.createtime > DateTime.Parse("2022-3-1")); + var sqls401 = sqls4.ToSql(); + var sqls402 = sqls4.ToList(); + + var sqls5 = fsql.Select().Where(a => a.createtime < DateTime.Parse("2022-5-1")); + var sqls501 = sqls5.ToSql(); + var sqls502 = sqls5.ToList(); + fsql.Aop.AuditValue += new EventHandler((_, e) => { diff --git a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj index 8179a363..58f962ef 100644 --- a/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj +++ b/Extensions/FreeSql.Extensions.BaseEntity/FreeSql.Extensions.BaseEntity.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin BaseEntity 是一种极简单的 CodeFirst 开发方式,特别对单表或多表CRUD,利用继承节省了每个实体类的重复属性(创建时间、ID等字段),软件删除等功能,进行 crud 操作时不必时常考虑仓储的使用. diff --git a/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj b/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj index 54f1468d..ade05a72 100644 --- a/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj +++ b/Extensions/FreeSql.Extensions.JsonMap/FreeSql.Extensions.JsonMap.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 扩展包,可实现实体类属性为对象时,以JSON形式映射存储. diff --git a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj index c67bbf96..2430ab50 100644 --- a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj +++ b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj @@ -2,7 +2,7 @@ netstandard2.0;netstandard2.1;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 扩展包,可实现【延时加载】属性. diff --git a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj index dcaa057d..2753d22b 100644 --- a/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj +++ b/Extensions/FreeSql.Extensions.Linq/FreeSql.Extensions.Linq.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 扩展包,实现 linq queryable 和 linq to sql 语法进行开发. diff --git a/Extensions/FreeSql.Generator/FreeSql.Generator.csproj b/Extensions/FreeSql.Generator/FreeSql.Generator.csproj index 1f3e5ce4..b563d8bf 100644 --- a/Extensions/FreeSql.Generator/FreeSql.Generator.csproj +++ b/Extensions/FreeSql.Generator/FreeSql.Generator.csproj @@ -12,7 +12,7 @@ 使用 FreeSql 快速生成数据库的实体类,安装:dotnet tool install -g FreeSql.Generator https://github.com/2881099/FreeSql https://github.com/2881099/FreeSql - 3.2.301 + 3.2.500 FreeSql DbFirst 实体生成器 diff --git a/FreeSql.All/FreeSql.All.csproj b/FreeSql.All/FreeSql.All.csproj index 48d381aa..e338f353 100644 --- a/FreeSql.All/FreeSql.All.csproj +++ b/FreeSql.All/FreeSql.All.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 全家桶,懒人专用 diff --git a/FreeSql.DbContext/FreeSql.DbContext.csproj b/FreeSql.DbContext/FreeSql.DbContext.csproj index a7e3da9b..50045f66 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.csproj +++ b/FreeSql.DbContext/FreeSql.DbContext.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;netcoreapp31;netcoreapp21;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Odbc, 达梦, 人大金仓, 神舟通用, 南大通用, 翰高, And Access diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index bdd16ff9..da7ace6b 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -538,14 +538,5 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - diff --git a/FreeSql.Repository/FreeSql.Repository.csproj b/FreeSql.Repository/FreeSql.Repository.csproj index d8de14ca..e26309aa 100644 --- a/FreeSql.Repository/FreeSql.Repository.csproj +++ b/FreeSql.Repository/FreeSql.Repository.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;netcoreapp31;netcoreapp21;net45;net40 - 3.2.301 + 3.2.500 FreeSql;ncc;YeXiangQin FreeSql Implementation of General Repository, Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/Access, and read/write separation、and split table. https://github.com/2881099/FreeSql/wiki/Repository diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs index 71177284..00eba288 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext/RepositoryTests.cs @@ -593,6 +593,55 @@ namespace FreeSql.Tests public Guid Id { get; set; } public string Name { get; set; } } + [Fact] + public void BeginEditIdentity() + { + g.sqlite.Delete().Where("1=1").ExecuteAffrows(); + var repo = g.sqlite.GetRepository(); + var cts = new[] { + new BeginEdit02 { Name = "1" }, + new BeginEdit02 { Name = "1_1" }, + new BeginEdit02 { Name = "1_2" }, + new BeginEdit02 { Name = "1_3" }, + new BeginEdit02 { Name = "2" }, + new BeginEdit02 { Name = "2_1" }, + new BeginEdit02 { Name = "2_2" } + }.ToList(); + repo.Insert(cts); + + repo.BeginEdit(cts); + + cts.Add(new BeginEdit02 { Name = "2_3" }); + cts[0].Name = "123123"; + cts.RemoveAt(1); + + Assert.Equal(3, repo.EndEdit()); + + g.sqlite.Delete().Where("1=1").ExecuteAffrows(); + repo = g.sqlite.GetRepository(); + cts = repo.Select.ToList(); + repo.BeginEdit(cts); + + cts.AddRange(new[] { + new BeginEdit02 { Name = "1" }, + new BeginEdit02 { Name = "1_1" }, + new BeginEdit02 { Name = "1_2" }, + new BeginEdit02 { Name = "1_3" }, + new BeginEdit02 { Name = "2" }, + new BeginEdit02 { Name = "2_1" }, + new BeginEdit02 { Name = "2_2" } + }); + + Assert.Equal(7, repo.EndEdit()); + } + class BeginEdit02 + { + [Column(IsIdentity = true)] + public int Id { get; set; } + public string Name { get; set; } + [Column(ServerTime = DateTimeKind.Utc)] + public DateTime UpdateTime { get; set; } + } [Fact] public void OrmScoped() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs index 5fa9883a..b68f9582 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/Curd/GBaseSelectTest.cs @@ -95,7 +95,7 @@ WHERE (a__Parent__Parent.Name = '粤语')", t0); var t1 = g.gbase.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); Assert.Equal(@"SELECT a.Id, a.Parent_id, a.Ddd, a.Name FROM Tag a -WHERE (exists(SELECT FIRST 1 1 +WHERE (exists(SELECT 1 FROM Tag t LEFT JOIN Tag t__Parent ON t__Parent.Id = t.Parent_id WHERE (t__Parent.Id = 10) AND (t.Parent_id = a.Id)))", t1); @@ -104,9 +104,9 @@ WHERE (exists(SELECT FIRST 1 1 var t2 = g.gbase.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); Assert.Equal(@"SELECT a.Id, a.Create_time, a.Is_deleted, a.Title, a.Url FROM Song a -WHERE (exists(SELECT FIRST 1 1 +WHERE (exists(SELECT 1 FROM Song_tag Mt_Ms - WHERE (Mt_Ms.Song_id = a.Id) AND (exists(SELECT FIRST 1 1 + WHERE (Mt_Ms.Song_id = a.Id) AND (exists(SELECT 1 FROM Tag t WHERE (t.Name = '国语') AND (t.Id = Mt_Ms.Tag_id)))))", t2); } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/ConvertTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/ConvertTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/ConvertTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/ConvertTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/DateTimeTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/DateTimeTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/DateTimeTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/DateTimeTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/MathTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/MathTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/MathTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/MathTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/OtherTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/OtherTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/OtherTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/OtherTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/StringTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/StringTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/StringTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/StringTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/TimeSpanTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/TimeSpanTest.cs similarity index 100% rename from FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/FirebirdExpression/TimeSpanTest.cs rename to FreeSql.Tests/FreeSql.Tests.Provider.GBase/GBase/GBaseExpression/TimeSpanTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/g.cs b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/g.cs index 8fcee4a4..6328e8f3 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.GBase/g.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.GBase/g.cs @@ -35,4 +35,6 @@ public class g }); public static IFreeSql gbase => gbaseLazy.Value; + //su - gbasedbt + //oninit -vy } diff --git a/FreeSql.Tests/FreeSql.Tests/Internal/UtilsTest.cs b/FreeSql.Tests/FreeSql.Tests/Internal/UtilsTest.cs index 250bae5c..f71d7ad5 100644 --- a/FreeSql.Tests/FreeSql.Tests/Internal/UtilsTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Internal/UtilsTest.cs @@ -46,5 +46,112 @@ namespace FreeSql.Tests.Internal Assert.Equal("p", ps2[0].ParameterName); Assert.Equal(typeof(SqlParameter), ps2[0].GetType()); } + + [Fact] + public void TestReplaceSqlConstString() + { + var dict = new Dictionary(); + string sql1 = "", sql2 = "", sql3 = ""; + + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202201"" SET ""msg"" = 'msg01', ""createtime"" = '2022-01-01 13:00:11' +WHERE (""id"" = '6252a2e6-5df3-bb10-00c1-bda60c4053fe')", dict); + Assert.Equal(3, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"INSERT INTO ""as_table_log_202201""(""id"", ""msg"", ""createtime"") VALUES('6252a2e6-5df3-bb10-00c1-bda60c4053fe', 'msg01', '2022-01-01 13:00:11'), ('6252a2e6-5df3-bb10-00c1-bda773467785', 'msg02', '2022-01-02 14:00:12')", dict); + Assert.Equal(6, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"DELETE FROM ""as_table_log_202205"" WHERE (""id"" = @exp_0 AND ""createtime"" between '2022-03-01 00:00:00' and '2022-05-01 00:00:00')", dict); + Assert.Equal(2, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202202"" SET ""msg"" = CASE ""id"" +WHEN '6252a2e6-5df3-bb10-00c1-bda818f4b93f' THEN 'msg03' +WHEN '6252a2e6-5df3-bb10-00c1-bda95dbadefd' THEN 'msg04' END, ""createtime"" = CASE ""id"" +WHEN '6252a2e6-5df3-bb10-00c1-bda818f4b93f' THEN '2022-02-02 15:00:13' +WHEN '6252a2e6-5df3-bb10-00c1-bda95dbadefd' THEN '2022-02-08 15:00:13' END +WHERE (""id"" IN ('6252a2e6-5df3-bb10-00c1-bda818f4b93f','6252a2e6-5df3-bb10-00c1-bda95dbadefd'))", dict); + Assert.Equal(6, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202207"" SET ""msg"" = 'msg07', ""createtime"" = '2022-07-01 00:00:00' +WHERE (""id"" = '6252a2e6-5df3-bb10-00c1-bdad01a608fb')", dict); + Assert.Equal(3, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202207"" SET ""msg"" = 'newmsg' +WHERE (""id"" = 'acc5df07-11a5-45b5-8af1-7b1ffac19f68')", dict); + Assert.Equal(2, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202203"" SET ""msg"" = 'newmsg' +WHERE (""id"" = '29bf2df7-3dfc-4005-a2e3-0421e50b2910') AND (""createtime"" between '2022-03-01 00:00:00' and '2022-05-01 00:00:00')", dict); + Assert.Equal(4, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202203"" SET ""msg"" = 'newmsg' +WHERE (""id"" = '4c9b5b32-49b2-44ee-beee-1e399e86b933') AND (""createtime"" > '2022-03-01 00:00:00' AND ""createtime"" < '2022-05-01 00:00:00')", dict); + Assert.Equal(4, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"UPDATE ""as_table_log_202201"" SET ""msg"" = 'newmsg' +WHERE (""id"" = '15d2a84f-bd72-4d73-8ad1-466ba8beea60') AND (""createtime"" < '2022-05-01 00:00:00')", dict); + Assert.Equal(3, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + + dict.Clear(); + sql2 = FreeSql.Internal.Utils.ReplaceSqlConstString(sql1 = @"SELECT * from (SELECT a.""id"", a.""msg"", a.""createtime"" +FROM ""as_table_log_202204"" a +WHERE (a.""createtime"" < '2022-05-01 00:00:00')) ftb + +UNION ALL + +SELECT * from (SELECT a.""id"", a.""msg"", a.""createtime"" +FROM ""as_table_log_202203"" a +WHERE (a.""createtime"" < '2022-05-01 00:00:00')) ftb + +UNION ALL + +SELECT * from (SELECT a.""id"", a.""msg"", a.""createtime"" +FROM ""as_table_log_202202"" a +WHERE (a.""createtime"" < '2022-05-01 00:00:00')) ftb + +UNION ALL + +SELECT * from (SELECT a.""id"", a.""msg"", a.""createtime"" +FROM ""as_table_log_202201"" a +WHERE (a.""createtime"" < '2022-05-01 00:00:00')) ftb", dict); + Assert.Equal(1, dict.Count); + sql3 = sql2; + dict.Select(a => sql3 = sql3.Replace(a.Key, "{0}".FormatMySql(a.Value))).ToList(); + Assert.Equal(sql1, sql3); + } } } diff --git a/FreeSql.Tests/FreeSql.Tests/Issues/804.cs b/FreeSql.Tests/FreeSql.Tests/Issues/804.cs index 3bab23f5..cf387d81 100644 --- a/FreeSql.Tests/FreeSql.Tests/Issues/804.cs +++ b/FreeSql.Tests/FreeSql.Tests/Issues/804.cs @@ -106,7 +106,7 @@ WHERE (strftime('%Y',a."CreateTime") = 2021) var d1 = fsql.Select().Where(r => r.CreateTime.Month == month).ToList(); var d2 = fsql.Select().Where(r => r.CreateTime.Year == year).ToList(); - var d5 = fsql.Select().Where(r => r.CreateTime.Year == 2021).ToList(); + var d5 = fsql.Select().Where(r => r.CreateTime.Year == 2022).ToList(); Assert.Single(dmonth1); Assert.Single(d1); diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteExpression/OtherTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteExpression/OtherTest.cs index c40c4e42..9562a3c6 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteExpression/OtherTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/SqliteExpression/OtherTest.cs @@ -77,6 +77,8 @@ namespace FreeSql.Tests.SqliteExpression { IEnumerable testlinqlist = new List(new[] { 1, 2, 3 }); var testlinq = select.Where(a => testlinqlist.Contains(a.Int)).ToList(); + var testlinq2list = new string[] { }; + var testlinq2 = g.sqlite.Delete().Where(a => testlinq2list.Contains(a.String)).ToSql(); //in not in var sql111 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.Int)).ToList(); diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs index a1db0c8d..19335b53 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs @@ -33,7 +33,7 @@ namespace FreeSql.Tests { is_lock = test.ratio < 1 //这里生成的SQL语句有问题 ratio = 0.9 或 1.9 或 2.1 等等都是生成的是1 }).Where(m => test.ratio < 1).ToSql(); - Assert.Equal(@"UPDATE TestDto SET is_lock = 2.1 < 1 + Assert.Equal(@"UPDATE `TestDto` SET `is_lock` = 2.1 < 1 WHERE (2.1 < 1)", sql); } diff --git a/FreeSql/DataAnnotations/TableAttribute.cs b/FreeSql/DataAnnotations/TableAttribute.cs index b08b5c4f..d6d2a4f3 100644 --- a/FreeSql/DataAnnotations/TableAttribute.cs +++ b/FreeSql/DataAnnotations/TableAttribute.cs @@ -1,6 +1,11 @@ -using System; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; using System.Collections.Concurrent; -using System.Linq.Expressions; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Text.RegularExpressions; namespace FreeSql.DataAnnotations { @@ -26,5 +31,348 @@ namespace FreeSql.DataAnnotations internal ConcurrentDictionary _columns { get; } = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); internal ConcurrentDictionary _navigates { get; } = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); internal ConcurrentDictionary _indexs { get; } = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + + /// + /// 格式:属性名=开始时间(递增) + /// 按年分表:[Table(Name = "log_{yyyy}", AsTable = "create_time=2022-1-1(1 year)")] + /// 按月分表:[Table(Name = "log_{yyyyMM}", AsTable = "create_time=2022-5-1(1 month)")] + /// 按日分表:[Table(Name = "log_{yyyyMMdd}", AsTable = "create_time=2022-5-1(5 day)")] + /// 按时分表:[Table(Name = "log_{yyyyMMddHH}", AsTable = "create_time=2022-5-1(6 hour)")] + /// + public string AsTable { get; set; } + + internal void ParseAsTable(TableInfo tb) + { + if (string.IsNullOrEmpty(AsTable) == false) + { + var atm = Regex.Match(AsTable, @"([\w_\d]+)\s*=\s*(\d\d\d\d)\s*\-\s*(\d\d?)\s*\-\s*(\d\d?)\s*\((\d+)\s*(year|month|day|hour)\)", RegexOptions.IgnoreCase); + if (atm.Success == false) + throw new Exception($"[Table(AsTable = \"{AsTable}\")] 特性值格式错误"); + + tb.AsTableColumn = tb.Columns.TryGetValue(atm.Groups[1].Value, out var trycol) ? trycol : + tb.ColumnsByCs.TryGetValue(atm.Groups[1].Value, out trycol) ? trycol : throw new Exception($"[Table(AsTable = xx)] 设置的属性名 {atm.Groups[1].Value} 不存在"); + if (tb.AsTableColumn.Attribute.MapType.NullableTypeOrThis() != typeof(DateTime)) + { + tb.AsTableColumn = null; + throw new Exception($"[Table(AsTable = xx)] 设置的属性名 {atm.Groups[1].Value} 不是 DateTime 类型"); + } + int.TryParse(atm.Groups[5].Value, out var atm5); + string atm6 = atm.Groups[6].Value.ToLower(); + tb.AsTableImpl = new DateTimeAsTableImpl(Name, DateTime.Parse($"{atm.Groups[2].Value}-{atm.Groups[3].Value}-{atm.Groups[4].Value}"), dt => + { + switch (atm6) + { + case "year": return dt.AddYears(atm5); + case "month": return dt.AddMonths(atm5); + case "day": return dt.AddDays(atm5); + case "hour": return dt.AddHours(atm5); + } + throw new NotImplementedException($"AsTable 未实现的功能 {AsTable}"); + }); + } + } + } + + public interface IAsTable + { + string[] AllTables { get; } + string GetTableNameByColumnValue(object columnValue, bool autoExpand = false); + string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2); + string[] GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils); + } + class DateTimeAsTableImpl : IAsTable + { + readonly object _lock = new object(); + readonly List _allTables = new List(); + readonly List _allTablesTime = new List(); + readonly DateTime _beginTime; + DateTime _lastTime; + Func _nextTimeFunc; + string _tableName; + Match _tableNameFormat; + static Regex _regTableNameFormat = new Regex(@"\{([^\\}]+)\}"); + + public DateTimeAsTableImpl(string tableName, DateTime beginTime, Func nextTimeFunc) + { + if (nextTimeFunc == null) throw new ArgumentException($"nextTimeFunc 不可以为 null"); + beginTime = beginTime.Date; //日期部分作为开始 + _beginTime = beginTime; + _nextTimeFunc = nextTimeFunc; + _tableName = tableName; + _tableNameFormat = _regTableNameFormat.Match(tableName); + if (string.IsNullOrEmpty(_tableNameFormat.Groups[1].Value)) throw new ArgumentException("tableName 格式错误,示例:“log_{yyyyMMdd}”"); + ExpandTable(beginTime, DateTime.Now); + } + + int GetTimestamp(DateTime dt) => (int)dt.Subtract(new DateTime(1970, 1, 1)).TotalSeconds; + void ExpandTable(DateTime beginTime, DateTime endTime) + { + if (beginTime > endTime) endTime = _nextTimeFunc(beginTime); + lock (_lock) + { + while (beginTime <= endTime) + { + var dtstr = beginTime.ToString(_tableNameFormat.Groups[1].Value); + var name = _tableName.Replace(_tableNameFormat.Groups[0].Value, dtstr); + if (_allTables.Contains(name)) throw new ArgumentException($"tableName:{_tableName} 生成了相同的分表名"); + _allTables.Insert(0, name); + _allTablesTime.Insert(0, beginTime); + _lastTime = beginTime; + beginTime = _nextTimeFunc(beginTime); + } + } + } + DateTime ParseColumnValue(object columnValue) + { + if (columnValue == null) throw new Exception($"分表字段值不能为 null"); + DateTime dt; + if (columnValue is DateTime || columnValue is DateTime?) + dt = (DateTime)columnValue; + else if (columnValue is string) + { + if (DateTime.TryParse(string.Concat(columnValue), out dt) == false) throw new Exception($"分表字段值 \"{columnValue}\" 不能转化成 DateTime"); + } + else if (columnValue is int || columnValue is long) + { + dt = new DateTime(1970, 1, 1).AddSeconds((double)columnValue); + } + else throw new Exception($"分表字段值 \"{columnValue}\" 不能转化成 DateTime"); + return dt; + } + + public string GetTableNameByColumnValue(object columnValue, bool autoExpand = false) + { + var dt = ParseColumnValue(columnValue); + if (dt < _beginTime) throw new Exception($"分表字段值 \"{dt.ToString("yyyy-MM-dd HH:mm:ss")}\" 不能小于 \"{_beginTime.ToString("yyyy-MM-dd HH:mm:ss")} \""); + var tmpTime = _nextTimeFunc(_lastTime); + if (dt >= tmpTime && autoExpand) + { + // 自动建表 + ExpandTable(tmpTime, dt); + } + lock (_lock) + { + var allTablesCount = _allTablesTime.Count; + for (var a = 0; a < allTablesCount; a++) + if (dt >= _allTablesTime[a]) + return _allTables[a]; + } + throw new Exception($"分表字段值 \"{dt.ToString("yyyy-MM-dd HH:mm:ss")}\" 未匹配到分表名"); + } + public string[] GetTableNamesByColumnValueRange(object columnValue1, object columnValue2) + { + var dt1 = ParseColumnValue(columnValue1); + var dt2 = ParseColumnValue(columnValue2); + if (dt1 > dt2) return new string[0]; + + lock (_lock) + { + int dt1idx = 0, dt2idx = 0; + var allTablesCount = _allTablesTime.Count; + if (dt1 < _beginTime) dt1idx = allTablesCount - 1; + else + { + for (var a = allTablesCount - 2; a > -1; a--) + { + if (dt1 < _allTablesTime[a]) + { + dt1idx = a + 1; + break; + } + } + } + if (dt2 > _allTablesTime.First()) dt2idx = 0; + else + { + for (var a = 0; a < allTablesCount; a++) + { + if (dt2 >= _allTablesTime[a]) + { + dt2idx = a; + break; + } + } + } + if (dt2idx == -1) return new string[0]; + + if (dt1idx == allTablesCount - 1 && dt2idx == 0) return _allTables.ToArray(); + var names = _allTables.GetRange(dt2idx, dt1idx - dt2idx + 1).ToArray(); + return names; + } + } + + static readonly ConcurrentDictionary _dicRegSqlWhereDateTimes = new ConcurrentDictionary(); + static Regex[] GetRegSqlWhereDateTimes(string columnName, string quoteParameterName) + { + return _dicRegSqlWhereDateTimes.GetOrAdd($"{columnName},{quoteParameterName}", cn => + { + cn = columnName.Replace("[", "\\[").Replace("]", "\\]").Replace(".", "\\."); + return new[] + { + //new Regex($@"({cn}\s*(<|<=|>|>=|=|between)\s*)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and\s+)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase), + //new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase), + + new Regex($@"({cn}\s*(<|<=|>|>=|=)\s*)(datetime|cdate|to_date)\(({quoteParameterName}[\w_]+)\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(<|<=|>|>=|=)(\s*))to_timestamp\(({quoteParameterName}[\w_]+)\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(<|<=|>|>=|=)(\s*))cast\(({quoteParameterName}[^w_]+) as (datetime|timestamp)\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(<|<=|>|>=|=)(\s*))({quoteParameterName}[^w_]+)::(datetime|timestamp)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(between)\s+{quoteParameterName}[\w_]+\s+and\s+)(datetime|cdate|to_date)\(({quoteParameterName}[\w_]+)\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(between)\s+{quoteParameterName}[\w_]+\s+and(\s+))to_timestamp\(({quoteParameterName}[\w_]+)\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(between)\s+{quoteParameterName}[\w_]+\s+and(\s+))cast\(({quoteParameterName}[^w_]+) as (datetime|timestamp)\)", RegexOptions.IgnoreCase), + new Regex($@"({cn}\s*(between)\s+{quoteParameterName}[\w_]+\s+and(\s+))({quoteParameterName}[^w_]+)::(datetime|timestamp)", RegexOptions.IgnoreCase), + + + new Regex($@"{cn}\s*between\s*'([^']+)'\s*and\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用 + new Regex($@"{cn}\s*between\s*{quoteParameterName}([\w_]+)\s*and\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase), + + new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'\s*and\s*{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用 + new Regex($@"{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)\s*and\s*{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase), + + new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用 + new Regex($@"{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase), + }; + }); + } + /// + /// 可以匹配以下条件(支持参数化): + /// `field` BETWEEN '2022-01-01 00:00:00' AND '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + /// `field` > '2022-01-01 00:00:00' + /// `field` >= '2022-01-01 00:00:00' + /// `field` < '2022-01-01 00:00:00' + /// `field` <= '2022-01-01 00:00:00' + /// + /// + /// + public string[] GetTableNamesBySqlWhere(string sqlWhere, List dbParams, SelectTableInfo tb, CommonUtils commonUtils) + { + if (string.IsNullOrWhiteSpace(sqlWhere)) return AllTables; + var quoteParameterName = commonUtils.QuoteParamterName(""); + var quoteParameterNameCharArray = quoteParameterName.ToCharArray(); + var columnName = commonUtils.QuoteSqlName(tb.Table.AsTableColumn.Attribute.Name); + + var dictParams = new Dictionary(); + var newSqlWhere = Utils.ReplaceSqlConstString(sqlWhere, dictParams, quoteParameterName); + //var tsqlWhere = Utils.ParseSqlWhereLevel1(sqlWhere); + + var regs = GetRegSqlWhereDateTimes($"{(string.IsNullOrWhiteSpace(tb.Alias) ? "" : $"{tb.Alias}.")}{commonUtils.QuoteSqlName(tb.Table.AsTableColumn.Attribute.Name)}", quoteParameterName); + for (var a = 0; a < 8; a++) newSqlWhere = regs[a].Replace(newSqlWhere, "$1$4"); + + //var m = regs[8].Match(newSqlWhere); + //if (m.Success) return GetTableNamesByColumnValueRange(m.Groups[1].Value, m.Groups[2].Value); + //m = m = regs[10].Match(newSqlWhere); + //if (m.Success) return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(m.Groups[2].Value), ParseColumnValue(m.Groups[4].Value)); + //m = regs[12].Match(newSqlWhere); + //if (m.Success) return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(m.Groups[2].Value)); + + var m = regs[9].Match(newSqlWhere); + if (m.Success) + { + var val1 = LocalGetParamValue(m.Groups[1].Value); + var val2 = LocalGetParamValue(m.Groups[2].Value); + if (val1 == null || val2 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}"); + return GetTableNamesByColumnValueRange(val1, val2); + } + m = regs[11].Match(newSqlWhere); + if (m.Success) + { + var val1 = LocalGetParamValue(m.Groups[2].Value); + var val2 = LocalGetParamValue(m.Groups[4].Value); + if (val1 == null || val2 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}"); + return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(val1), ParseColumnValue(val2)); + } + m = regs[13].Match(newSqlWhere); + if (m.Success) + { + var val1 = LocalGetParamValue(m.Groups[2].Value); + if (val1 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}"); + return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(val1)); + } + return AllTables; + + object LocalGetParamValue(string paramName) + { + if (dictParams.TryGetValue(quoteParameterName + paramName, out var trydictVal)) return trydictVal; + return dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[2].Value).FirstOrDefault()?.Value; + } + string[] LocalGetTables(string opt1, string opt2, DateTime val1, DateTime val2) + { + switch (opt1) + { + case "<": + case "<=": + if (opt1 == "<") val1 = val1.AddSeconds(-1); + switch (opt2) + { + case "<": + val2 = val2.AddSeconds(-1); + return GetTableNamesByColumnValueRange(_beginTime, val1 > val2 ? val2 : val1); + case "<=": + return GetTableNamesByColumnValueRange(_beginTime, val1 > val2 ? val2 : val1); + case ">": + val2 = val2.AddSeconds(1); + return GetTableNamesByColumnValueRange(val2, val1); + case ">=": + return GetTableNamesByColumnValueRange(val2, val1); + } + break; + case ">": + case ">=": + if (opt1 == ">") val1 = val1.AddSeconds(1); + switch (opt2) + { + case "<": + val2 = val2.AddSeconds(-1); + return GetTableNamesByColumnValueRange(val1, val2); + case "<=": + return GetTableNamesByColumnValueRange(val1, val2); + case ">": + val2 = val2.AddSeconds(1); + return GetTableNamesByColumnValueRange(val1 > val2 ? val1 : val2, _lastTime); + case ">=": + return GetTableNamesByColumnValueRange(val1 > val2 ? val1 : val2, _lastTime); + } + break; + } + return AllTables; + } + string[] LocalGetTables2(string opt, DateTime val1) + { + switch (m.Groups[1].Value) + { + case "<": + val1 = val1.AddSeconds(-1); + return GetTableNamesByColumnValueRange(_beginTime, val1); + case "<=": + return GetTableNamesByColumnValueRange(_beginTime, val1); + case ">": + val1 = val1.AddSeconds(1); + return GetTableNamesByColumnValueRange(val1, _lastTime); + case ">=": + return GetTableNamesByColumnValueRange(val1, _lastTime); + } + return AllTables; + } + } + + public string[] AllTables + { + get + { + lock (_lock) + { + return _allTables.ToArray(); + } + } + } } } diff --git a/FreeSql/Extensions/EntityUtilExtensions.cs b/FreeSql/Extensions/EntityUtilExtensions.cs index 97732054..b19f1316 100644 --- a/FreeSql/Extensions/EntityUtilExtensions.cs +++ b/FreeSql/Extensions/EntityUtilExtensions.cs @@ -604,7 +604,15 @@ namespace FreeSql.Extensions.EntityUtil exps.Add(Expression.Label(returnTarget, Expression.Constant(new string[0]))); return Expression.Lambda>(Expression.Block(new[] { var1Ret, var1Parm, var2Parm }, exps), new[] { parm1, parm2, parm3 }).Compile(); }); - return func(entity1, entity2, isEqual); + var result = func(entity1, entity2, isEqual); + var tmptb = orm.CodeFirst.GetTableByEntity(entityType); + if (tmptb.ColumnsByCanUpdateDbUpdateValue.Length > 0) { + if (isEqual && result.Length + tmptb.ColumnsByCanUpdateDbUpdateValue.Length == tmptb.ColumnsByCs.Count) + return result.Concat(tmptb.ColumnsByCanUpdateDbUpdateValue.Select(a => a.Attribute.Name)).ToArray(); + if (!isEqual && result.Length == tmptb.ColumnsByCanUpdateDbUpdateValue.Length) + return new string[0]; + } + return result; } static ConcurrentDictionary>> _dicSetEntityIncrByWithPropertyName = new ConcurrentDictionary>>(); diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index 25abbdf8..16576b0e 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,7 +2,7 @@ netstandard2.1;netstandard2.0;net451;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql is the ORM in .NetCore, .NetFramework, And Xamarin. It supports Mysql, Postgresql, SqlServer, Oracle, Sqlite, Firebird, Odbc, 达梦, 人大金仓, 神舟通用, 南大通用, 翰高, And Access diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 55a8f429..be8688b0 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -397,6 +397,31 @@ 禁用 CodeFirst 同步结构迁移 + + + 格式:属性名=开始时间(递增) + 按年分表:[Table(Name = "log_{yyyy}", AsTable = "create_time=2022-1-1(1 year)")] + 按月分表:[Table(Name = "log_{yyyyMM}", AsTable = "create_time=2022-5-1(1 month)")] + 按日分表:[Table(Name = "log_{yyyyMMdd}", AsTable = "create_time=2022-5-1(5 day)")] + 按时分表:[Table(Name = "log_{yyyyMMddHH}", AsTable = "create_time=2022-5-1(6 hour)")] + + + + + 可以匹配以下条件(支持参数化): + `field` BETWEEN '2022-01-01 00:00:00' AND '2022-03-01 00:00:00' + `field` > '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + `field` > '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + `field` >= '2022-01-01 00:00:00' AND `field` < '2022-03-01 00:00:00' + `field` >= '2022-01-01 00:00:00' AND `field` <= '2022-03-01 00:00:00' + `field` > '2022-01-01 00:00:00' + `field` >= '2022-01-01 00:00:00' + `field` < '2022-01-01 00:00:00' + `field` <= '2022-01-01 00:00:00' + + + + 数据库表名 diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 1e52e23c..01278f96 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1690,6 +1690,7 @@ namespace FreeSql.Internal public abstract string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc); public abstract string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc); + public string ExpressionConstDateTime(Expression exp) => exp is ConstantExpression operandExpConst ? formatSql(Utils.GetDataReaderValue(typeof(DateTime), operandExpConst.Value), null, null, null) : null; public enum ExpressionStyle { diff --git a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs index b0fe1e4b..03439075 100644 --- a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs +++ b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs @@ -95,7 +95,9 @@ namespace FreeSql.Internal.CommonProvider { if (objects == null) return; var syncObjects = objects.Where(a => a.entityType != null && a.entityType != typeof(object) && _dicSycedGetOrAdd(a.entityType).ContainsKey(GetTableNameLowerOrUpper(a.tableName)) == false && GetTableByEntity(a.entityType)?.DisableSyncStructure == false) - .Select(a => new TypeAndName(a.entityType, GetTableNameLowerOrUpper(a.tableName))).ToArray(); + .Select(a => new TypeAndName(a.entityType, GetTableNameLowerOrUpper(a.tableName))) + .Where(a => !(string.IsNullOrEmpty(a.tableName) == true && GetTableByEntity(a.entityType)?.AsTableImpl != null)) + .ToArray(); if (syncObjects.Any() == false) return; var before = new Aop.SyncStructureBeforeEventArgs(syncObjects.Select(a => a.entityType).ToArray()); _orm.Aop.SyncStructureBeforeHandler?.Invoke(this, before); diff --git a/FreeSql/Internal/CommonProvider/DeleteProvider.cs b/FreeSql/Internal/CommonProvider/DeleteProvider.cs index 1e84d341..0fe798c0 100644 --- a/FreeSql/Internal/CommonProvider/DeleteProvider.cs +++ b/FreeSql/Internal/CommonProvider/DeleteProvider.cs @@ -10,8 +10,7 @@ using System.Threading.Tasks; namespace FreeSql.Internal.CommonProvider { - - public abstract partial class DeleteProvider : IDelete + public abstract partial class DeleteProvider { public IFreeSql _orm; public CommonUtils _commonUtils; @@ -26,7 +25,10 @@ namespace FreeSql.Internal.CommonProvider public DbConnection _connection; public int _commandTimeout = 0; public Action _interceptSql; + } + public abstract partial class DeleteProvider : DeleteProvider, IDelete + { public DeleteProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) { _orm = orm; @@ -66,28 +68,32 @@ namespace FreeSql.Internal.CommonProvider public int ExecuteAffrows() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return 0; - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var affrows = 0; - Exception exception = null; - try + DbParameter[] dbParms = null; + ToSqlFetch(sb => { - affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); + if (dbParms == null) dbParms = _params.ToArray(); + var sql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + affrows += _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) this.ClearData(); return affrows; } public abstract List ExecuteDeleted(); @@ -164,17 +170,80 @@ namespace FreeSql.Internal.CommonProvider public virtual string ToSql() { - if (_whereTimes <= 0) return null; - var sb = new StringBuilder().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" WHERE ").Append(_where); + if (_whereTimes <= 0 || _where.Length == 0) return null; + var sb = new StringBuilder(); + ToSqlFetch(sql => + { + sb.Append(sql).Append("\r\n\r\n;\r\n\r\n"); + }); + if (sb.Length > 0) sb.Remove(sb.Length - 9, 9); + return sb.ToString(); + } + + public void ToSqlFetch(Action fetch) + { + if (_whereTimes <= 0 || _where.Length == 0) return; + var newwhere = new StringBuilder().Append(" WHERE ").Append(_where); if (_whereGlobalFilter.Any()) { var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false); if (string.IsNullOrEmpty(globalFilterCondi) == false) - sb.Append(" AND ").Append(globalFilterCondi); + newwhere.Append(" AND ").Append(globalFilterCondi); } + + var sb = new StringBuilder(); + if (_table.AsTableImpl != null) + { + var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, new SelectTableInfo { Table = _table }, _commonUtils); + foreach (var name in names) + { + _tableRule = old => name; + sb.Clear().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere); + _interceptSql?.Invoke(sb); + fetch(sb); + } + return; + } + + sb.Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere); _interceptSql?.Invoke(sb); - return sb.ToString(); + fetch(sb); + sb.Clear(); } +#if net40 +#else + async public Task ToSqlFetchAsync(Func fetchAsync) + { + if (_whereTimes <= 0 || _where.Length == 0) return; + var newwhere = new StringBuilder().Append(" WHERE ").Append(_where); + + if (_whereGlobalFilter.Any()) + { + var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false); + if (string.IsNullOrEmpty(globalFilterCondi) == false) + newwhere.Append(" AND ").Append(globalFilterCondi); + } + + var sb = new StringBuilder(); + if (_table.AsTableImpl != null) + { + var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, new SelectTableInfo { Table = _table }, _commonUtils); + foreach (var name in names) + { + _tableRule = old => name; + sb.Clear().Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere); + _interceptSql?.Invoke(sb); + await fetchAsync(sb); + } + return; + } + + sb.Append("DELETE FROM ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(newwhere); + _interceptSql?.Invoke(sb); + await fetchAsync(sb); + sb.Clear(); + } +#endif } } diff --git a/FreeSql/Internal/CommonProvider/DeleteProviderAsync.cs b/FreeSql/Internal/CommonProvider/DeleteProviderAsync.cs index 85073150..d2115b5f 100644 --- a/FreeSql/Internal/CommonProvider/DeleteProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/DeleteProviderAsync.cs @@ -16,28 +16,32 @@ namespace FreeSql.Internal.CommonProvider #else async public Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return 0; - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var affrows = 0; - Exception exception = null; - try + DbParameter[] dbParms = null; + await ToSqlFetchAsync(async sb => { - affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); + if (dbParms == null) dbParms = _params.ToArray(); + var sql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + affrows += await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) this.ClearData(); return affrows; } public abstract Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default); diff --git a/FreeSql/Internal/CommonProvider/InsertProvider.cs b/FreeSql/Internal/CommonProvider/InsertProvider.cs index 36450189..fb2e67ea 100644 --- a/FreeSql/Internal/CommonProvider/InsertProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertProvider.cs @@ -14,12 +14,11 @@ using System.Collections; namespace FreeSql.Internal.CommonProvider { - public abstract partial class InsertProvider : IInsert where T1 : class + public abstract partial class InsertProvider { public IFreeSql _orm; public CommonUtils _commonUtils; public CommonExpression _commonExpression; - public List _source = new List(); public Dictionary _ignore = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public Dictionary _auditValueChangedDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public TableInfo _table; @@ -28,11 +27,17 @@ namespace FreeSql.Internal.CommonProvider public bool _noneParameter, _insertIdentity; public int _batchValuesLimit, _batchParameterLimit; public bool _batchAutoTransaction = true; - public Action> _batchProgress; public DbParameter[] _params; public DbTransaction _transaction; public DbConnection _connection; public int _commandTimeout = 0; + } + + public abstract partial class InsertProvider : InsertProvider, IInsert where T1 : class + { + public List _source = new List(); + internal List _sourceOld; + public Action> _batchProgress; public InsertProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { @@ -43,6 +48,7 @@ namespace FreeSql.Internal.CommonProvider _noneParameter = _orm.CodeFirst.IsNoneCommandParameter; if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); IgnoreCanInsert(); + _sourceOld = _source; } /// @@ -62,6 +68,7 @@ namespace FreeSql.Internal.CommonProvider _batchProgress = null; _insertIdentity = false; _source.Clear(); + _sourceOld = _source; _ignore.Clear(); _auditValueChangedDict.Clear(); _params = null; @@ -189,7 +196,7 @@ namespace FreeSql.Internal.CommonProvider } #region 参数化数据限制,或values数量限制 - protected List[] SplitSource(int valuesLimit, int parameterLimit) + protected List[] SplitSource(int valuesLimit, int parameterLimit, bool isAsTableSplited = false) { valuesLimit = valuesLimit - 1; parameterLimit = parameterLimit - 1; @@ -198,6 +205,28 @@ namespace FreeSql.Internal.CommonProvider if (_source == null || _source.Any() == false) return new List[0]; if (_source.Count == 1) return new[] { _source }; + if (_table.AsTableImpl != null && isAsTableSplited == false) + { + var atarr = _source.Select(a => new + { + item = a, + splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a), true) + }).GroupBy(a => a.splitKey, a => a.item).ToArray(); + if (atarr.Length > 1) + { + var oldSource = _source; + var arrret = new List>(); + foreach (var item in atarr) + { + _source = item.ToList(); + var itemret = SplitSource(valuesLimit + 1, parameterLimit + 1, true); + arrret.AddRange(itemret); + } + _source = oldSource; + return arrret.ToArray(); + } + } + var takeMax = valuesLimit; if (_noneParameter == false) { @@ -510,8 +539,19 @@ namespace FreeSql.Internal.CommonProvider protected string TableRuleInvoke() { var tbname = _table?.DbName ?? ""; - if (_tableRule == null) return tbname; - var newname = _tableRule(tbname); + if (_tableRule == null && _table.AsTableImpl == null) return tbname; + string newname = null; + if (_table.AsTableImpl != null) + { + if (_source.Any()) + newname = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(_source.FirstOrDefault())); + else if (_tableRule == null) + newname = _table.AsTableImpl.GetTableNameByColumnValue(DateTime.Now); + else + newname = _tableRule(_table.DbName); + } + else + newname = _tableRule(_table.DbName); if (newname == tbname) return tbname; if (string.IsNullOrEmpty(newname)) return tbname; if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower(); @@ -532,6 +572,7 @@ namespace FreeSql.Internal.CommonProvider public IInsert AsType(Type entityType) { if (entityType == typeof(object)) throw new Exception("IInsert.AsType 参数不支持指定为 object"); + if (entityType == typeof(T1)) return this; if (entityType == _table.Type) return this; var newtb = _commonUtils.GetTableByEntity(entityType); _table = newtb ?? throw new Exception("IInsert.AsType 参数错误,请传入正确的实体类型"); @@ -540,14 +581,38 @@ namespace FreeSql.Internal.CommonProvider return this; } - public virtual string ToSql() => ToSqlValuesOrSelectUnionAllExtension102(true, null, null); + public virtual string ToSql() => ToSqlValuesOrSelectUnionAllExtension103(true, null, null, false); - public string ToSqlValuesOrSelectUnionAll(bool isValues = true) => ToSqlValuesOrSelectUnionAllExtension102(isValues, null, null); - public string ToSqlValuesOrSelectUnionAllExtension101(bool isValues, Action onrow) => ToSqlValuesOrSelectUnionAllExtension102(isValues, null, onrow); - public string ToSqlValuesOrSelectUnionAllExtension102(bool isValues, Action onrowPre, Action onrow) + public string ToSqlValuesOrSelectUnionAll(bool isValues = true) => ToSqlValuesOrSelectUnionAllExtension103(isValues, null, null, false); + public string ToSqlValuesOrSelectUnionAllExtension101(bool isValues, Action onrow) => ToSqlValuesOrSelectUnionAllExtension103(isValues, null, onrow, false); + public string ToSqlValuesOrSelectUnionAllExtension102(bool isValues, Action onrowPre, Action onrow) => ToSqlValuesOrSelectUnionAllExtension103(isValues, onrowPre, onrow, false); + string ToSqlValuesOrSelectUnionAllExtension103(bool isValues, Action onrowPre, Action onrow, bool isAsTableSplited) { if (_source == null || _source.Any() == false) return null; var sb = new StringBuilder(); + + if (_table.AsTableImpl != null && isAsTableSplited == false && _source == _sourceOld) + { + var atarr = _source.Select(a => new + { + item = a, + splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a), true) + }).GroupBy(a => a.splitKey, a => a.item).ToArray(); + if (atarr.Length > 1) + { + var oldSource = _source; + var arrret = new List>(); + foreach (var item in atarr) + { + _source = item.ToList(); + sb.Append(ToSqlValuesOrSelectUnionAllExtension103(isValues, onrowPre, onrow, true)).Append("\r\n\r\n;\r\n\r\n"); + } + _source = oldSource; + if (sb.Length > 0) sb.Remove(sb.Length - 9, 9); + return sb.ToString(); + } + } + sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append('('); var colidx = 0; foreach (var col in _table.Columns.Values) @@ -628,6 +693,13 @@ namespace FreeSql.Internal.CommonProvider else val = Utils.GetDataReaderValue(col.Item2, val); } + switch (_orm.Ado.DataType) + { + case DataType.SqlServer: + case DataType.OdbcSqlServer: + if (val?.Equals(DateTime.MinValue) == true) val = new DateTime(1970, 1, 1); + break; + } row[rowIndex++] = val; } dt.Rows.Add(row); diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 58326a91..d3d13dea 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -460,7 +460,67 @@ namespace FreeSql.Internal.CommonProvider protected List> GetTableRuleUnions() { var unions = new List>(); - var trs = _tableRules.Any() ? _tableRules : new List>(new[] { new Func((type, oldname) => null) }); + var trs = _tableRules.Any() ? _tableRules : new List>(new [] { new Func((type, oldname) => null) }); + + if (trs.Count == 1 && _tables.Any(a => a.Table.AsTableImpl != null && string.IsNullOrWhiteSpace(trs[0](a.Table.Type, a.Table.DbName)) == true)) + { + string[] LocalGetTableNames(SelectTableInfo tb) + { + var trname = trs[0](tb.Table.Type, tb.Table.DbName); + if (tb.Table.AsTableImpl != null && string.IsNullOrWhiteSpace(trname) == true) + { + string[] aret = null; + if (_where.Length == 0) aret = tb.Table.AsTableImpl.AllTables; + else aret = tb.Table.AsTableImpl.GetTableNamesBySqlWhere(_where.ToString(), _params, tb, _commonUtils); + if (aret.Any() == false) aret = tb.Table.AsTableImpl.AllTables.Take(1).ToArray(); + + for (var a = 0; a < aret.Length; a++) + { + if (_orm.CodeFirst.IsSyncStructureToLower) aret[a] = aret[a].ToLower(); + if (_orm.CodeFirst.IsSyncStructureToUpper) aret[a] = aret[a].ToUpper(); + if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(tb.Table.Type, aret[a]); + } + return aret; + } + if (string.IsNullOrWhiteSpace(trname) == false) + { + if (trname.IndexOf(' ') == -1) //还可以这样:select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList() + { + if (_orm.CodeFirst.IsSyncStructureToLower) trname = trname.ToLower(); + if (_orm.CodeFirst.IsSyncStructureToUpper) trname = trname.ToUpper(); + if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(tb.Table.Type, trname); + } + else + trname = trname.Replace(" \r\n", " \r\n "); + return new string[] { trname }; + } + return new string[] { tb.Table.DbName }; + } + var tbnames = _tables.GroupBy(a => a.Table.Type).Select(g => _tables.Where(a => a.Table.Type == g.Key).FirstOrDefault()).Select(a => new { Tb = a, Names = LocalGetTableNames(a) }).ToList(); + var dict = new Dictionary(); + tbnames.ForEach(a => + { + dict.Add(a.Tb.Table.Type, a.Names[0]); + }); + unions.Add(dict); + for (var a = 0; a < tbnames.Count; a++) + { + if (tbnames[a].Names.Length <= 1) continue; + var unionsCount = unions.Count; + for (var b = 1; b < tbnames[a].Names.Length; b++) + { + for (var d = 0; d < unionsCount; d++) + { + dict = new Dictionary(); + foreach (var uit in unions[d]) + dict.Add(uit.Key, uit.Key == tbnames[a].Tb.Table.Type ? tbnames[a].Names[b] : uit.Value); + unions.Add(dict); + } + } + } + return unions; + } + if (trs.Any() == false) trs.Add(new Func((type, oldname) => null)); foreach (var tr in trs) { var dict = new Dictionary(); diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index ea98dc63..71af0381 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -12,13 +12,11 @@ using System.Threading.Tasks; namespace FreeSql.Internal.CommonProvider { - - public abstract partial class UpdateProvider : IUpdate + public abstract partial class UpdateProvider { public IFreeSql _orm; public CommonUtils _commonUtils; public CommonExpression _commonExpression; - public List _source = new List(); public Dictionary _ignore = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public Dictionary _auditValueChangedDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public TableInfo _table; @@ -33,12 +31,18 @@ namespace FreeSql.Internal.CommonProvider public bool _noneParameter; public int _batchRowsLimit, _batchParameterLimit; public bool _batchAutoTransaction = true; - public Action> _batchProgress; public DbTransaction _transaction; public DbConnection _connection; public int _commandTimeout = 0; public Action _interceptSql; public byte[] _updateVersionValue; + } + + public abstract partial class UpdateProvider : UpdateProvider, IUpdate + { + public List _source = new List(); + public List _sourceOld; + public Action> _batchProgress; public UpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) { @@ -52,6 +56,7 @@ namespace FreeSql.Internal.CommonProvider if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); IgnoreCanUpdate(); _whereGlobalFilter = _orm.GlobalFilter.GetFilters(); + _sourceOld = _source; } /// @@ -69,6 +74,7 @@ namespace FreeSql.Internal.CommonProvider _batchRowsLimit = _batchParameterLimit = 0; _batchAutoTransaction = true; _source.Clear(); + _sourceOld = _source; _ignore.Clear(); _auditValueChangedDict.Clear(); _where.Clear(); @@ -138,7 +144,7 @@ namespace FreeSql.Internal.CommonProvider } #region 参数化数据限制,或values数量限制 - protected internal List[] SplitSource(int valuesLimit, int parameterLimit) + protected internal List[] SplitSource(int valuesLimit, int parameterLimit, bool isAsTableSplited = false) { valuesLimit = valuesLimit - 1; parameterLimit = parameterLimit - 1; @@ -147,6 +153,28 @@ namespace FreeSql.Internal.CommonProvider if (_source == null || _source.Any() == false) return new List[0]; if (_source.Count == 1) return new[] { _source }; + if (_table.AsTableImpl != null && isAsTableSplited == false) + { + var atarr = _source.Select(a => new + { + item = a, + splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a), true) + }).GroupBy(a => a.splitKey, a => a.item).ToArray(); + if (atarr.Length > 1) + { + var oldSource = _source; + var arrret = new List>(); + foreach (var item in atarr) + { + _source = item.ToList(); + var itemret = SplitSource(valuesLimit + 1, parameterLimit + 1, true); + arrret.AddRange(itemret); + } + _source = oldSource; + return arrret.ToArray(); + } + } + var takeMax = valuesLimit; if (_noneParameter == false) { @@ -314,28 +342,33 @@ namespace FreeSql.Internal.CommonProvider protected int RawExecuteAffrows() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return 0; - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var affrows = 0; - Exception exception = null; - try + DbParameter[] dbParms = null; + ToSqlFetch(sb => { - affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(affrows, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) dbParms = _params.Concat(_paramsSource).ToArray(); + var sql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var affrowstmp = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(affrowstmp, sql, dbParms); + affrows += affrowstmp; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); return affrows; } @@ -692,8 +725,19 @@ namespace FreeSql.Internal.CommonProvider protected string TableRuleInvoke() { - if (_tableRule == null) return _table.DbName; - var newname = _tableRule(_table.DbName); + if (_tableRule == null && _table.AsTableImpl == null) return _table.DbName; + string newname = null; + if (_table.AsTableImpl != null) + { + if (_source.Any()) + newname = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(_source.FirstOrDefault())); + else if (_tableRule == null) + newname = _table.AsTableImpl.GetTableNameByColumnValue(DateTime.Now); + else + newname = _tableRule(_table.DbName); + } + else + newname = _tableRule(_table.DbName); if (newname == _table.DbName) return _table.DbName; if (string.IsNullOrEmpty(newname)) return _table.DbName; if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower(); @@ -725,9 +769,114 @@ namespace FreeSql.Internal.CommonProvider public virtual string ToSql() { - if (_where.Length == 0 && _source.Any() == false) return null; + if (_source.Any()) + { + var sb1 = new StringBuilder(); + ToSqlExtension110(sb1, false); + return sb1.ToString(); + } + + if (_where.Length == 0) return null; + + var sb2 = new StringBuilder(); + ToSqlFetch(sql => + { + sb2.Append(sql).Append("\r\n\r\n;\r\n\r\n"); + }); + if (sb2.Length > 0) sb2.Remove(sb2.Length - 9, 9); + return sb2.ToString(); + } + + public void ToSqlFetch(Action fetch) + { + if (_source.Any()) + { + var sb1 = new StringBuilder(); + ToSqlExtension110(sb1, false); + fetch(sb1); + return; + } + if (_where.Length == 0) return; + var newwhere = new StringBuilder(); + ToSqlWhere(newwhere); var sb = new StringBuilder(); + if (_table.AsTableImpl != null) + { + var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, new SelectTableInfo { Table = _table }, _commonUtils); + foreach (var name in names) + { + _tableRule = old => name; + ToSqlExtension110(sb.Clear(), true); + fetch(sb); + } + return; + } + + ToSqlExtension110(sb, true); + fetch(sb); + } +#if net40 +#else + async public Task ToSqlFetchAsync(Func fetchAsync) + { + if (_source.Any()) + { + var sb1 = new StringBuilder(); + ToSqlExtension110(sb1, false); + await fetchAsync(sb1); + sb1.Clear(); + return; + } + if (_where.Length == 0) return; + var newwhere = new StringBuilder(); + ToSqlWhere(newwhere); + + var sb = new StringBuilder(); + if (_table.AsTableImpl != null) + { + var names = _table.AsTableImpl.GetTableNamesBySqlWhere(newwhere.ToString(), _params, new SelectTableInfo { Table = _table }, _commonUtils); + foreach (var name in names) + { + _tableRule = old => name; + ToSqlExtension110(sb.Clear(), true); + await fetchAsync(sb); + } + return; + } + + ToSqlExtension110(sb, true); + await fetchAsync(sb); + sb.Clear(); + } +#endif + public virtual void ToSqlExtension110(StringBuilder sb, bool isAsTableSplited) + { + if (_where.Length == 0 && _source.Any() == false) return; + + if (_table.AsTableImpl != null && isAsTableSplited == false && _source == _sourceOld && _source.Any()) + { + var atarr = _source.Select(a => new + { + item = a, + splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a)) + }).GroupBy(a => a.splitKey, a => a.item).ToArray(); + if (atarr.Length > 1) + { + var oldSource = _source; + var arrret = new List>(); + foreach (var item in atarr) + { + _source = item.ToList(); + ToSqlExtension110(sb, true); + sb.Append("\r\n\r\n;\r\n\r\n"); + } + _source = oldSource; + if (sb.Length > 0) sb.Remove(sb.Length - 9, 9); + return; + } + } + sb.Append("UPDATE ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" SET "); if (_set.Length > 0) @@ -763,12 +912,12 @@ namespace FreeSql.Internal.CommonProvider ++colidx; } } - if (colidx == 0) return null; + if (colidx == 0) return; } else if (_source.Count > 1) { //批量保存 Source - if (_tempPrimarys.Any() == false) return null; + if (_tempPrimarys.Any() == false) return; var caseWhen = new StringBuilder(); caseWhen.Append("CASE "); @@ -818,10 +967,10 @@ namespace FreeSql.Internal.CommonProvider ++colidx; } } - if (colidx == 0) return null; + if (colidx == 0) return; } else if (_setIncr.Length == 0) - return null; + return; if (_setIncr.Length > 0) sb.Append(_set.Length > 0 ? _setIncr.ToString() : _setIncr.ToString().Substring(2)); @@ -844,7 +993,13 @@ namespace FreeSql.Internal.CommonProvider else sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.IsNull(vcname, 0)).Append(" + 1"); } + ToSqlWhere(sb); + _interceptSql?.Invoke(sb); + return; + } + public virtual void ToSqlWhere(StringBuilder sb) + { sb.Append(" \r\nWHERE "); if (_source.Any()) { @@ -868,9 +1023,6 @@ namespace FreeSql.Internal.CommonProvider if (string.IsNullOrEmpty(versionCondi) == false) sb.Append(" AND ").Append(versionCondi); } - - _interceptSql?.Invoke(sb); - return sb.ToString(); } } } diff --git a/FreeSql/Internal/CommonProvider/UpdateProviderAsync.cs b/FreeSql/Internal/CommonProvider/UpdateProviderAsync.cs index 9f8aa53a..8a2127fe 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProviderAsync.cs @@ -167,28 +167,33 @@ namespace FreeSql.Internal.CommonProvider async protected Task RawExecuteAffrowsAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return 0; - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var affrows = 0; - Exception exception = null; - try + DbParameter[] dbParms = null; + await ToSqlFetchAsync(async sb => { - affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(affrows, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) dbParms = _params.Concat(_paramsSource).ToArray(); + var sql = sb.ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var affrowstmp = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(affrowstmp, sql, dbParms); + affrows += affrowstmp; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, affrows); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); return affrows; } protected abstract Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default); diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index 93be8c72..315eca86 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -125,7 +125,9 @@ namespace FreeSql.Internal { if (!string.IsNullOrEmpty(trytb.Name)) attr.Name = trytb.Name; if (!string.IsNullOrEmpty(trytb.OldName)) attr.OldName = trytb.OldName; - if (trytb._DisableSyncStructure != null) attr._DisableSyncStructure = trytb.DisableSyncStructure; + if (trytb._DisableSyncStructure != null) attr._DisableSyncStructure = trytb.DisableSyncStructure; + if (!string.IsNullOrEmpty(trytb.AsTable)) attr.AsTable = trytb.AsTable; + } var attrs = type.GetCustomAttributes(typeof(TableAttribute), false); foreach (var tryattrobj in attrs) @@ -135,10 +137,12 @@ namespace FreeSql.Internal if (!string.IsNullOrEmpty(tryattr.Name)) attr.Name = tryattr.Name; if (!string.IsNullOrEmpty(tryattr.OldName)) attr.OldName = tryattr.OldName; if (tryattr._DisableSyncStructure != null) attr._DisableSyncStructure = tryattr.DisableSyncStructure; + if (!string.IsNullOrEmpty(tryattr.AsTable)) attr.AsTable = tryattr.AsTable; } if (!string.IsNullOrEmpty(attr.Name)) return attr; if (!string.IsNullOrEmpty(attr.OldName)) return attr; if (attr._DisableSyncStructure != null) return attr; + if (!string.IsNullOrEmpty(attr.AsTable)) return attr; return null; } public ColumnAttribute GetEntityColumnAttribute(Type type, PropertyInfo proto) diff --git a/FreeSql/Internal/Model/TableInfo.cs b/FreeSql/Internal/Model/TableInfo.cs index 4058a626..7de85216 100644 --- a/FreeSql/Internal/Model/TableInfo.cs +++ b/FreeSql/Internal/Model/TableInfo.cs @@ -17,6 +17,7 @@ namespace FreeSql.Internal.Model public Dictionary ColumnsByCs { get; set; } = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public Dictionary ColumnsByCsIgnore { get; set; } = new Dictionary(StringComparer.CurrentCultureIgnoreCase); public ColumnInfo[] ColumnsByPosition { get; set; } + public ColumnInfo[] ColumnsByCanUpdateDbUpdateValue { get; set; } public ColumnInfo[] Primarys { get; set; } public IndexInfo[] Indexes { get; set; } public string CsName { get; set; } @@ -27,6 +28,8 @@ namespace FreeSql.Internal.Model public bool IsRereadSql { get; internal set; } public bool IsDictionaryType { get; internal set; } + public IAsTable AsTableImpl { get; internal set; } + public ColumnInfo AsTableColumn { get; internal set; } public ColumnInfo VersionColumn { get; set; } ConcurrentDictionary _refs { get; } = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 6108c130..08fc5aff 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -393,6 +393,7 @@ namespace FreeSql.Internal if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || trytb.VersionColumn.Attribute.MapType.IsNumberType() == false && trytb.VersionColumn.Attribute.MapType != typeof(byte[])) throw new Exception($"属性{trytb.VersionColumn.CsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[],并且不可为 Nullable"); } + tbattr?.ParseAsTable(trytb); var indexesDict = new Dictionary(StringComparer.CurrentCultureIgnoreCase); //从数据库查找主键、自增、索引 @@ -483,6 +484,7 @@ namespace FreeSql.Internal trytb.ColumnsByPosition = columnsList.Where(a => a.Attribute.Position > 0).OrderBy(a => a.Attribute.Position) .Concat(columnsList.Where(a => a.Attribute.Position == 0)) .Concat(columnsList.Where(a => a.Attribute.Position < 0).OrderBy(a => a.Attribute.Position)).ToArray(); + trytb.ColumnsByCanUpdateDbUpdateValue = columnsList.Where(a => a.Attribute.CanUpdate == true && string.IsNullOrEmpty(a.DbUpdateValue) == false).ToArray(); trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray(); if (trytb.Primarys.Any() == false) @@ -2266,5 +2268,196 @@ namespace FreeSql.Internal name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_"); return char.IsLetter(name, 0) ? name : string.Concat("_", name); } + + public static string ReplaceSqlConstString(string sql, Dictionary parms, string paramPrefix = "@") + { + var nsb = new StringBuilder(); + var sidx = 0; + var pidx = 0; + var ptmpPrefix = ""; + while (true) + { + pidx++; + ptmpPrefix = $"{paramPrefix}p{pidx}"; + if (sql.Contains(ptmpPrefix) == false) break; + } + pidx = 0; + while (sidx < sql.Length) + { + var chr = sql[sidx++]; + if (chr != '\'') + { + nsb.Append(chr); + continue; + } + var startIdx = sidx; + var startLength = 0; + while (sidx < sql.Length) + { + var chrb = sql[sidx++]; + if (chrb != '\'') + { + startLength++; + continue; + } + if (sidx < sql.Length && sql[sidx] == '\'') + { + startLength += 2; + continue; + } + break; + } + if (startLength > 0) + { + var pvalue = sql.Substring(startIdx, startLength).Replace("''", "'"); + var pname = parms.Where(a => a.Value == pvalue).Select(a => a.Key).FirstOrDefault(); + if (string.IsNullOrEmpty(pname)) + { + while (true) + { + pidx++; + pname = $"{ptmpPrefix}{pidx}"; + if (parms.ContainsKey(pname) == false) break; + } + } + nsb.Append(pname); + if (parms.ContainsKey(pname) == false) parms.Add(pname, pvalue); + } + } + return nsb.ToString(); + } + + internal static string ParseSqlWhereLevel1(string sql) + { + var dictParms = new Dictionary(); + var rawsql = ReplaceSqlConstString(sql, dictParms).Trim(); + sql = Regex.Replace(rawsql, @"[\r\n\t]", " "); + var remidx = sql.IndexOf("WHERE "); + if (remidx != -1) sql = sql.Substring(remidx + 6); + + //sql = Regex.Replace(sql, @"\s*([@:\?][\w_]+)\s*(<|<=|>|>=|=)\s*((\w+)\s*\.)?([\w_]+)"); + return LocalProcessBrackets(sql); + + + string LocalProcessBrackets(string locsql) + { + var sidx = 0; + var ltcou = 0; + var ltidxStack = new Stack(); + while (sidx < locsql.Length) + { + var chr = locsql[sidx++]; + if (chr == '(') + { + ltcou++; + ltidxStack.Push(sidx - 1); + } + if (chr == ')') + { + ltcou--; + var ltidx = ltidxStack.Pop(); + var ltidx2 = ltidx; + var sidx2 = sidx; + while(sidx < locsql.Length) + { + var chr2 = locsql[sidx]; + if (chr2 == ')') + { + if (ltidxStack.First() == ltidx - 1) + { + ltidx = ltidxStack.Pop(); + sidx++; + } + } + break; + } + if (ltidx == 0 && sidx == locsql.Length) + { + locsql = locsql.Substring(1, sidx - 2); + break; + } + var sqlLeft = ltidx == 0 ? "" : locsql.Remove(ltidx); + var sqlMid = locsql.Substring(ltidx, sidx - ltidx); + var sqlMidNew = sqlMid; + var sqlRight = sidx == locsql.Length ? "" : locsql.Substring(sidx); + var mLeft = Regex.Match(sqlLeft, @" (and|or|not)\s*$", RegexOptions.IgnoreCase); + if (mLeft.Success) + { + switch (mLeft.Groups[1].Value) + { + case "and": + sqlMidNew = sqlMid.Substring(1, sqlMid.Length - 2).Trim(); + break; + case "or": + sqlMidNew = ""; + break; + case "not": + break; + } + } + sidx -= sqlMid.Length - sqlMidNew.Length; + locsql = $"{sqlLeft}{sqlMidNew}{sqlRight}"; + } + } + return locsql; + } + } + + static string ParseSqlWhereLevel12(string sql) + { + var dictParms = new Dictionary(); + var rawsql = ReplaceSqlConstString(sql, dictParms); + sql = Regex.Replace(rawsql, @"[\r\n\t]", " "); + var remidx = sql.IndexOf("WHERE "); + if (remidx != -1) sql = sql.Substring(remidx + 6); + + Dictionary dicSqlParts = new Dictionary(); + var nsb = new StringBuilder(); + var swliRoot = new SqlWhereLogicInfo(); + var swliCurrent = swliRoot; + + LocalParseSqlWhere(sql); + return nsb.ToString(); + + void LocalParseSqlWhere(string sqlPart) + { + var sidx = 0; + var ltcou = 0; + var ltidxStack = new Stack(); + while (sidx < sqlPart.Length) + { + var chr = sqlPart[sidx++]; + if (chr == '(') + { + ltcou++; + ltidxStack.Push(sidx - 1); + //swliCurrent.Filters.Add() + } + if (chr == ')') + { + ltcou--; + var ltidx = ltidxStack.Pop(); + var pvalue = sqlPart.Substring(ltidx, sidx - ltidx); + break; + //var pname = $"@p_{Guid.NewGuid().ToString("N")}"; + //dicSqlParts.Add(pname, pvalue); + //LocalParseSqlWhere(sqlPart); + //var ltsql = sqlPart.Substring(Math.Max(0, ltidx - 5), ltidx); + //if (Regex.IsMatch(ltsql, @"(and|or|not)$")) + // ltsb.Last().Append("1=1"); + } + } + } + } + + class SqlWhereLogicInfo + { + public string Field { get; set; } + public string Operator { get; set; } + public object Value { get; set; } + + public DynamicFilterLogic Logic { get; set; } + public List Filters { get; set; } + } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs index 4d8f1c3f..77a6dfea 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs @@ -34,7 +34,7 @@ namespace FreeSql.ClickHouse case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as Int8)"; case "System.Char": return $"substr(cast({getExp(operandExp)} as String), 1, 1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as DateTime)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as DateTime)"; case "System.Decimal": return $"cast({getExp(operandExp)} as Decimal128(19))"; case "System.Double": return $"cast({getExp(operandExp)} as Float64)"; case "System.Int16": return $"cast({getExp(operandExp)} as Int16)"; @@ -62,7 +62,7 @@ namespace FreeSql.ClickHouse case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as Int8)"; case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as String), 1, 1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as DateTime)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as DateTime)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as Decimal128(19))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as Float64)"; case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as Int16)"; @@ -419,10 +419,10 @@ namespace FreeSql.ClickHouse var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as DateTime)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as DateTime)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as DateTime)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as DateTime)"; } } else @@ -555,7 +555,7 @@ namespace FreeSql.ClickHouse case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as Int8)"; case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as String), 1, 1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as DateTime)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as DateTime)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as Decimal128(19))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as Float64)"; case "ToInt16": diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs index 6d81e48b..ecd48033 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseUtils.cs @@ -21,7 +21,9 @@ namespace FreeSql.ClickHouse { if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; var dbtype = (DbType?)_orm.CodeFirst.GetDbInfo(type)?.type; - DbParameter ret = new ClickHouseDbParameter { ParameterName = parameterName, DbType = dbtype ?? default, Value = value };//QuoteParamterName(parameterName) + DbParameter ret = new ClickHouseDbParameter { ParameterName = parameterName };//QuoteParamterName(parameterName) + if (dbtype != null) ret.DbType = dbtype.Value; + ret.Value = value; if (col != null) { var dbtype2 = (DbType)_orm.DbFirst.GetDbType(new DatabaseModel.DbColumnInfo { DbTypeText = col.DbTypeText, DbTypeTextFull = col.Attribute.DbType, MaxLength = col.DbSize }); diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseDelete.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseDelete.cs index c950f12b..9439b5bf 100644 --- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseDelete.cs +++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseDelete.cs @@ -16,20 +16,16 @@ namespace FreeSql.ClickHouse.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException("FreeSql.ClickHouse.Curd 暂未实现"); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.ClickHouse 未实现该功能"); + public override string ToSql() { - return base.ToSql().Replace("DELETE FROM", "ALTER TABLE").Replace("WHERE", "DELETE WHERE"); + return base.ToSql().Replace("DELETE FROM ", "ALTER TABLE ").Replace(" WHERE ", " DELETE WHERE "); } + #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException("FreeSql.ClickHouse.Curd 暂未实现"); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.ClickHouse 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs index db63dad4..5853eff0 100644 --- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs +++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseInsert.cs @@ -80,27 +80,7 @@ namespace FreeSql.ClickHouse.Curd _orm.Aop.CurdAfterHandler?.Invoke(this, after); } } - else - { - var sql = this.ToSql(); - before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); - try - { - affrows = _orm.Ado.ExecuteNonQuery(_connection, null, CommandType.Text, sql, _commandTimeout, _params); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - return affrows; - } + return base.RawExecuteAffrows(); } private IDictionary GetValue(T u, System.Reflection.PropertyInfo[] columns) @@ -210,27 +190,7 @@ namespace FreeSql.ClickHouse.Curd _orm.Aop.CurdAfterHandler?.Invoke(this, after); } } - else - { - var sql = this.ToSql(); - before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); - try - { - affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, null, CommandType.Text, sql, _commandTimeout, _params); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, affrows); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - return affrows; - } + return await base.RawExecuteAffrowsAsync(cancellationToken); } async protected override Task RawExecuteIdentityAsync(CancellationToken cancellationToken = default) diff --git a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs index 9e69b3c9..c941af96 100644 --- a/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs +++ b/Providers/FreeSql.Provider.ClickHouse/Curd/ClickHouseUpdate.cs @@ -65,11 +65,33 @@ namespace FreeSql.ClickHouse.Curd sb.Append(")"); } - public override string ToSql() + public override void ToSqlExtension110(StringBuilder sb, bool isAsTableSplited) { - if (_where.Length == 0 && _source.Any() == false) return null; + if (_where.Length == 0 && _source.Any() == false) return; + + if (_table.AsTableImpl != null && isAsTableSplited == false && _source == _sourceOld && _source.Any()) + { + var atarr = _source.Select(a => new + { + item = a, + splitKey = _table.AsTableImpl.GetTableNameByColumnValue(_table.AsTableColumn.GetValue(a)) + }).GroupBy(a => a.splitKey, a => a.item).ToArray(); + if (atarr.Length > 1) + { + var oldSource = _source; + var arrret = new List>(); + foreach (var item in atarr) + { + _source = item.ToList(); + ToSqlExtension110(sb, true); + sb.Append("\r\n\r\n;\r\n\r\n"); + } + _source = oldSource; + if (sb.Length > 0) sb.Remove(sb.Length - 9, 9); + return; + } + } - var sb = new StringBuilder(); sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" UPDATE "); if (_set.Length > 0) @@ -105,12 +127,12 @@ namespace FreeSql.ClickHouse.Curd ++colidx; } } - if (colidx == 0) return null; + if (colidx == 0) return; } else if (_source.Count > 1) { //批量保存 Source - if (_tempPrimarys.Any() == false) return null; + if (_tempPrimarys.Any() == false) return; var caseWhen = new StringBuilder(); ToSqlCase(caseWhen, _tempPrimarys); @@ -160,10 +182,10 @@ namespace FreeSql.ClickHouse.Curd ++colidx; } } - if (colidx == 0) return null; + if (colidx == 0) return; } else if (_setIncr.Length == 0) - return null; + return; if (_setIncr.Length > 0) sb.Append(_set.Length > 0 ? _setIncr.ToString() : _setIncr.ToString().Substring(2)); @@ -186,33 +208,9 @@ namespace FreeSql.ClickHouse.Curd else sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.IsNull(vcname, 0)).Append(" + 1"); } - - sb.Append(" \r\nWHERE "); - if (_source.Any()) - { - if (_tempPrimarys.Any() == false) throw new ArgumentException($"{_table.Type.DisplayCsharp()} 没有定义主键,无法使用 SetSource,请尝试 SetDto"); - sb.Append('(').Append(_commonUtils.WhereItems(_tempPrimarys, "", _source)).Append(')'); - } - - if (_where.Length > 0) - sb.Append(_source.Any() ? _where.ToString() : _where.ToString().Substring(5)); - - if (_whereGlobalFilter.Any()) - { - var globalFilterCondi = _commonExpression.GetWhereCascadeSql(new SelectTableInfo { Table = _table }, _whereGlobalFilter, false); - if (string.IsNullOrEmpty(globalFilterCondi) == false) - sb.Append(" AND ").Append(globalFilterCondi); - } - - if (_table.VersionColumn != null) - { - var versionCondi = WhereCaseSource(_table.VersionColumn.CsName, sqlval => sqlval); - if (string.IsNullOrEmpty(versionCondi) == false) - sb.Append(" AND ").Append(versionCondi); - } - + ToSqlWhere(sb); _interceptSql?.Invoke(sb); - return sb.ToString(); + return; } protected override int SplitExecuteAffrows(int valuesLimit, int parameterLimit) diff --git a/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj b/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj index a5f1583d..c495bf58 100644 --- a/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj +++ b/Providers/FreeSql.Provider.ClickHouse/FreeSql.Provider.ClickHouse.csproj @@ -3,7 +3,7 @@ netstandard2.1 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin;ChenBo FreeSql 数据库实现,基于 ClickHouse.Client Ado.net diff --git a/Providers/FreeSql.Provider.Custom/Curd/CustomUpdate.cs b/Providers/FreeSql.Provider.Custom/Curd/CustomUpdate.cs index 338d2d29..c67d5f5c 100644 --- a/Providers/FreeSql.Provider.Custom/Curd/CustomUpdate.cs +++ b/Providers/FreeSql.Provider.Custom/Curd/CustomUpdate.cs @@ -23,7 +23,7 @@ namespace FreeSql.Custom public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : _utils.Adapter.UpdateBatchSplitLimit, _batchParameterLimit > 0 ? _batchParameterLimit : 255); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : _utils.Adapter.UpdateBatchSplitLimit, _batchParameterLimit > 0 ? _batchParameterLimit : 255); - protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.Custom 未实现该功能 未实现该功能"); + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.Custom 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -65,7 +65,7 @@ namespace FreeSql.Custom public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : _utils.Adapter.UpdateBatchSplitLimit, _batchParameterLimit > 0 ? _batchParameterLimit : 255, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : _utils.Adapter.UpdateBatchSplitLimit, _batchParameterLimit > 0 ? _batchParameterLimit : 255, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Custom 未实现该功能 未实现该功能"); + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Custom 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj b/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj index a830fc80..d8889460 100644 --- a/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj +++ b/Providers/FreeSql.Provider.Custom/FreeSql.Provider.Custom.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库自定义适配,访问所有数据库 diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs index 800b2a10..59f31b49 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.Dameng.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.Dameng 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Dameng 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs index d069b5bf..8eb4d26a 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.Dameng.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs index 96eb38b8..7bd489d4 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs @@ -21,11 +21,7 @@ namespace FreeSql.Dameng.Curd public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.Dameng 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -69,10 +65,7 @@ namespace FreeSql.Dameng.Curd public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Dameng 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Dameng/DamengUtils.cs b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs index 5dc1bd37..cfee3da5 100644 --- a/Providers/FreeSql.Provider.Dameng/DamengUtils.cs +++ b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs @@ -40,7 +40,9 @@ namespace FreeSql.Dameng } break; } - var ret = new DmParameter { ParameterName = QuoteParamterName(parameterName), DmSqlType = dbtype ?? default, Value = value }; + var ret = new DmParameter { ParameterName = QuoteParamterName(parameterName) }; + if (dbtype != null) ret.DmSqlType = dbtype.Value; + ret.Value = value; _params?.Add(ret); return ret; } diff --git a/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj index 2c598242..d61598e2 100644 --- a/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj +++ b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 达梦数据库 Ado.net (DmProvider) diff --git a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdDelete.cs b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdDelete.cs index 84afe01b..7a100a0d 100644 --- a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdDelete.cs +++ b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.Firebird.Curd public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.TypeLazy ?? _table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.Firebird.Curd #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.TypeLazy ?? _table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs index 4d45fb34..10b07f3c 100644 --- a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.Firebird.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdUpdate.cs b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdUpdate.cs index 464bf9dd..1ea75626 100644 --- a/Providers/FreeSql.Provider.Firebird/Curd/FirebirdUpdate.cs +++ b/Providers/FreeSql.Provider.Firebird/Curd/FirebirdUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -24,40 +25,48 @@ namespace FreeSql.Firebird.Curd protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"new.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"new.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -105,40 +114,48 @@ namespace FreeSql.Firebird.Curd async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"new.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"new.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs b/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs index fea3bbae..f5c55353 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdExpression.cs @@ -32,7 +32,7 @@ namespace FreeSql.Firebird case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as smallint)"; case "System.Char": return $"substring(cast({getExp(operandExp)} as varchar(10)) from 1 for 1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as timestamp)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as timestamp)"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(18,6))"; case "System.Double": return $"cast({getExp(operandExp)} as decimal(18,10))"; case "System.Int16": return $"cast({getExp(operandExp)} as smallint)"; @@ -60,7 +60,7 @@ namespace FreeSql.Firebird case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as smallint)"; case "System.Char": return $"substring(cast({getExp(callExp.Arguments[0])} as varchar(10)) from 1 for 1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as timestamp)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as timestamp)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(18,6))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(18,10))"; case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as smallint)"; @@ -389,10 +389,10 @@ namespace FreeSql.Firebird var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"mod({isLeapYearArgs1},4)=0 AND mod({isLeapYearArgs1},100)<>0 OR mod({isLeapYearArgs1},400)=0"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as timestamp)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as timestamp)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as timestamp)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as timestamp)"; } } else @@ -504,7 +504,7 @@ namespace FreeSql.Firebird case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as smallint)"; case "ToChar": return $"substring(cast({getExp(exp.Arguments[0])} as varchar(10)) from 1 for 1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as timestamp)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as timestamp)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(18,6))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(18,10))"; case "ToInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)"; diff --git a/Providers/FreeSql.Provider.Firebird/FirebirdUtils.cs b/Providers/FreeSql.Provider.Firebird/FirebirdUtils.cs index bb65b3e0..2655e2f0 100644 --- a/Providers/FreeSql.Provider.Firebird/FirebirdUtils.cs +++ b/Providers/FreeSql.Provider.Firebird/FirebirdUtils.cs @@ -35,7 +35,7 @@ namespace FreeSql.Firebird break; } } - ret.FbDbType = dbtype ?? default; + if (dbtype != null) ret.FbDbType = dbtype.Value; _params?.Add(ret); return ret; } diff --git a/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj b/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj index f17a1785..5a408391 100644 --- a/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj +++ b/Providers/FreeSql.Provider.Firebird/FreeSql.Provider.Firebird.csproj @@ -2,7 +2,7 @@ netstandard2.0;net452 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 Firebird diff --git a/Providers/FreeSql.Provider.GBase/Curd/GBaseDelete.cs b/Providers/FreeSql.Provider.GBase/Curd/GBaseDelete.cs index 7e9f7b90..27b4948e 100644 --- a/Providers/FreeSql.Provider.GBase/Curd/GBaseDelete.cs +++ b/Providers/FreeSql.Provider.GBase/Curd/GBaseDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.GBase.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.GBase 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.GBase 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs b/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs index b54366b0..170653d9 100644 --- a/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.GBase/Curd/GBaseInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.GBase.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.GBase/Curd/GBaseUpdate.cs b/Providers/FreeSql.Provider.GBase/Curd/GBaseUpdate.cs index 20eb39b4..8d10fcc3 100644 --- a/Providers/FreeSql.Provider.GBase/Curd/GBaseUpdate.cs +++ b/Providers/FreeSql.Provider.GBase/Curd/GBaseUpdate.cs @@ -22,10 +22,7 @@ namespace FreeSql.GBase.Curd public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.GBase 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -69,10 +66,7 @@ namespace FreeSql.GBase.Curd public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.GBase 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj b/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj index abb3c2f1..823a487c 100644 --- a/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj +++ b/Providers/FreeSql.Provider.GBase/FreeSql.Provider.GBase.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 3.2.301 + 3.2.500 true FreeSql;GBase FreeSql 数据库实现,基于 南大通用 8.0 diff --git a/Providers/FreeSql.Provider.GBase/GBaseUtils.cs b/Providers/FreeSql.Provider.GBase/GBaseUtils.cs index 79f1e9d7..b2c243ca 100644 --- a/Providers/FreeSql.Provider.GBase/GBaseUtils.cs +++ b/Providers/FreeSql.Provider.GBase/GBaseUtils.cs @@ -35,7 +35,7 @@ namespace FreeSql.GBase break; } } - ret.OdbcType = dbtype ?? default; + if (dbtype != null) ret.OdbcType = dbtype.Value; _params?.Add(ret); return ret; } diff --git a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESDelete.cs b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESDelete.cs index cd91741b..0ca3dd5b 100644 --- a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESDelete.cs +++ b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.KingbaseES public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.KingbaseES #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs index 6a4fd4a4..a529cf51 100644 --- a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESInsertOrUpdate.cs @@ -35,6 +35,7 @@ namespace FreeSql.KingbaseES .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESUpdate.cs b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESUpdate.cs index ac3927b4..8201153a 100644 --- a/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESUpdate.cs +++ b/Providers/FreeSql.Provider.KingbaseES/Curd/KingbaseESUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -32,40 +33,48 @@ namespace FreeSql.KingbaseES protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -129,40 +138,48 @@ namespace FreeSql.KingbaseES async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj b/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj index ce720076..2de6eea0 100644 --- a/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj +++ b/Providers/FreeSql.Provider.KingbaseES/FreeSql.Provider.KingbaseES.csproj @@ -2,7 +2,7 @@ netstandard2.0;net461 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 人大金仓数据库 V008R003 Ado.Net (Kdbndp) diff --git a/Providers/FreeSql.Provider.KingbaseES/KingbaseESExpression.cs b/Providers/FreeSql.Provider.KingbaseES/KingbaseESExpression.cs index 4acc5c81..a35cc007 100644 --- a/Providers/FreeSql.Provider.KingbaseES/KingbaseESExpression.cs +++ b/Providers/FreeSql.Provider.KingbaseES/KingbaseESExpression.cs @@ -35,7 +35,7 @@ namespace FreeSql.KingbaseES case "System.Boolean": return $"(({getExp(operandExp)})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(operandExp)})::int2"; case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(operandExp)})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"({getExp(operandExp)})::timestamp"; case "System.Decimal": return $"({getExp(operandExp)})::numeric"; case "System.Double": return $"({getExp(operandExp)})::float8"; case "System.Int16": return $"({getExp(operandExp)})::int2"; @@ -63,7 +63,7 @@ namespace FreeSql.KingbaseES case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2"; case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"({getExp(callExp.Arguments[0])})::timestamp"; case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric"; case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8"; case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2"; @@ -468,10 +468,10 @@ namespace FreeSql.KingbaseES var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})::int8%4=0 AND ({isLeapYearArgs1})::int8%100<>0 OR ({isLeapYearArgs1})::int8%400=0)"; - case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; } } else @@ -605,7 +605,7 @@ namespace FreeSql.KingbaseES case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "ToByte": return $"({getExp(exp.Arguments[0])})::int2"; case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)"; - case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric"; case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8"; case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2"; diff --git a/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessDelete.cs b/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessDelete.cs index 3c5fd1fd..814bf6f1 100644 --- a/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessDelete.cs +++ b/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.MsAccess.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.MsAccess 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.MsAccess 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessUpdate.cs b/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessUpdate.cs index 65bfa99e..e24525e9 100644 --- a/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessUpdate.cs +++ b/Providers/FreeSql.Provider.MsAccess/Curd/MsAccessUpdate.cs @@ -27,10 +27,7 @@ namespace FreeSql.MsAccess.Curd public override IUpdate BatchOptions(int rowsLimit, int parameterLimit, bool autoTransaction = true) => throw new NotImplementedException("蛋疼的 access 插入只能一条一条执行,不支持 values(..),(..) 也不支持 select .. UNION ALL select .."); - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.MsAccess 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -72,10 +69,7 @@ namespace FreeSql.MsAccess.Curd public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(1, 1000, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(1, 1000, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.MsAccess 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj b/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj index c59031b5..3c7346a2 100644 --- a/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj +++ b/Providers/FreeSql.Provider.MsAccess/FreeSql.Provider.MsAccess.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库 Ms Access 实现 diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs index 74031933..5f5431a4 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.MySql.Curd public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.MySql.Curd #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs index 46fc44d6..85769c95 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs @@ -37,6 +37,7 @@ namespace FreeSql.MySql.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs index 9611e331..e4ae587a 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -31,40 +32,48 @@ namespace FreeSql.MySql.Curd protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -112,40 +121,48 @@ namespace FreeSql.MySql.Curd async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj index 983cedfd..2a24a2ee 100644 --- a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj +++ b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj @@ -2,7 +2,7 @@ netstandard2.0;net452;net451;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 MySql 5.6,Ado.Net 驱动是 MySql.Data(Oracle官方) diff --git a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs index 6e27d68d..57aee99b 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlExpression.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlExpression.cs @@ -34,7 +34,7 @@ namespace FreeSql.MySql case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as unsigned)"; case "System.Char": return $"substr(cast({getExp(operandExp)} as char), 1, 1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as datetime)"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))"; case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))"; case "System.Int16": @@ -62,7 +62,7 @@ namespace FreeSql.MySql case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as unsigned)"; case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as char), 1, 1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as datetime)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))"; case "System.Int16": @@ -401,10 +401,10 @@ namespace FreeSql.MySql var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; } } else @@ -537,7 +537,7 @@ namespace FreeSql.MySql case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as unsigned)"; case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as char), 1, 1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))"; case "ToInt16": diff --git a/Providers/FreeSql.Provider.MySql/MySqlUtils.cs b/Providers/FreeSql.Provider.MySql/MySqlUtils.cs index ed0b68e9..7ca8d271 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlUtils.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlUtils.cs @@ -46,7 +46,10 @@ namespace FreeSql.MySql if (value != null) ret.Value = (value as MygisGeometry).AsText(); } else - ret.MySqlDbType = dbtype ?? default; + { + if (dbtype != null) + ret.MySqlDbType = dbtype.Value; + } _params?.Add(ret); return ret; } diff --git a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj index a782465c..a15df93c 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj +++ b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;net45;netstandard2.1;netcoreapp2.1;netcoreapp3.1; - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 MySql 5.6,Ado.Net 驱动是 MySqlConnector diff --git a/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs b/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs index a242f2d7..7a7b8084 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs +++ b/Providers/FreeSql.Provider.MySqlConnector/MySqlConnectorUtils.cs @@ -44,7 +44,8 @@ namespace FreeSql.MySql } else { - ret.MySqlDbType = dbtype ?? default; + if (dbtype != null) + ret.MySqlDbType = dbtype.Value; if (ret.MySqlDbType == MySqlDbType.Enum && value != null) ret.Value = EnumValueToMySql(value); } diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengDelete.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengDelete.cs index a57a8a84..8ee23ec8 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.Odbc.Dameng { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Odbc.Dameng 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Odbc.Dameng 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs index abf627c7..0f363b68 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.Odbc.Dameng .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengUpdate.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengUpdate.cs index 6454901d..f454c2bd 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengUpdate.cs @@ -22,11 +22,7 @@ namespace FreeSql.Odbc.Dameng public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Odbc.Dameng 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -70,10 +66,7 @@ namespace FreeSql.Odbc.Dameng public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Odbc.Dameng 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs index a1c95f01..9ce96dbb 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs @@ -36,7 +36,9 @@ namespace FreeSql.Odbc.Dameng value = string.Concat(value); break; } - var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), OdbcType = dbtype ?? default, Value = value }; + var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName) }; + if (dbtype != null) ret.OdbcType = dbtype.Value; + ret.Value = value; _params?.Add(ret); return ret; } @@ -62,7 +64,9 @@ namespace FreeSql.Odbc.Dameng value = string.Concat(value); break; } - var ret = new OdbcParameter { ParameterName = $":{name}", OdbcType = dbtype ?? default, Value = value }; + var ret = new OdbcParameter { ParameterName = $":{name}" }; + if (dbtype != null) ret.OdbcType = dbtype.Value; + ret.Value = value; return ret; }); diff --git a/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs b/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs index e7c00f5f..d2104316 100644 --- a/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/Default/OdbcUtils.cs @@ -18,9 +18,10 @@ namespace FreeSql.Odbc.Default { if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1); - var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), Value = value }; + var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName) }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (tp != null) ret.OdbcType = (OdbcType)tp.Value; + ret.Value = value; _params?.Add(ret); return ret; } @@ -29,9 +30,10 @@ namespace FreeSql.Odbc.Default Utils.GetDbParamtersByObject(sql, obj, null, (name, type, value) => { if (value?.Equals(DateTime.MinValue) == true) value = new DateTime(1970, 1, 1); - var ret = new OdbcParameter { ParameterName = $"@{name}", Value = value }; + var ret = new OdbcParameter { ParameterName = $"@{name}" }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; if (tp != null) ret.OdbcType = (OdbcType)tp.Value; + ret.Value = value; return ret; }); diff --git a/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj b/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj index 604d78a3..0e419f84 100644 --- a/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj +++ b/Providers/FreeSql.Provider.Odbc/FreeSql.Provider.Odbc.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库 Odbc 实现,基于 {Oracle}、{SQL Server}、{MySQL ODBC 8.0 Unicode Driver}、{PostgreSQL Unicode(x64)}、{DM8 ODBC Driver} 专用访问实现,以及通用 Odbc 访问所有数据库 diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESDelete.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESDelete.cs index edb6d6aa..e4a381b9 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.Odbc.KingbaseES public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.Odbc.KingbaseES #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs index 7eaf2fee..34b6b4ea 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESInsertOrUpdate.cs @@ -37,6 +37,7 @@ namespace FreeSql.Odbc.KingbaseES .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESUpdate.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESUpdate.cs index 3a54ecea..14265fd5 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/Curd/OdbcKingbaseESUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -32,40 +33,48 @@ namespace FreeSql.Odbc.KingbaseES protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -129,40 +138,48 @@ namespace FreeSql.Odbc.KingbaseES async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESExpression.cs b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESExpression.cs index 12901b30..cb33402c 100644 --- a/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/KingbaseES/OdbcKingbaseESExpression.cs @@ -35,7 +35,7 @@ namespace FreeSql.Odbc.KingbaseES case "System.Boolean": return $"(({getExp(operandExp)})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(operandExp)})::int2"; case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(operandExp)})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"({getExp(operandExp)})::timestamp"; case "System.Decimal": return $"({getExp(operandExp)})::numeric"; case "System.Double": return $"({getExp(operandExp)})::float8"; case "System.Int16": return $"({getExp(operandExp)})::int2"; @@ -63,7 +63,7 @@ namespace FreeSql.Odbc.KingbaseES case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2"; case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"({getExp(callExp.Arguments[0])})::timestamp"; case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric"; case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8"; case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2"; @@ -468,10 +468,10 @@ namespace FreeSql.Odbc.KingbaseES var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})::int8%4=0 AND ({isLeapYearArgs1})::int8%100<>0 OR ({isLeapYearArgs1})::int8%400=0)"; - case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; } } else @@ -605,7 +605,7 @@ namespace FreeSql.Odbc.KingbaseES case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "ToByte": return $"({getExp(exp.Arguments[0])})::int2"; case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)"; - case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric"; case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8"; case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2"; diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs index 144e880f..fdf91e47 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.Odbc.MySql public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.Odbc.MySql #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs index 822fb089..6feac813 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs @@ -36,6 +36,7 @@ namespace FreeSql.Odbc.MySql .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs index dbfaa014..1b8f4adb 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -31,40 +32,48 @@ namespace FreeSql.Odbc.MySql protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -112,40 +121,48 @@ namespace FreeSql.Odbc.MySql async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs index e9b5e4a9..a0734a6d 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlExpression.cs @@ -32,7 +32,7 @@ namespace FreeSql.Odbc.MySql case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as unsigned)"; case "System.Char": return $"substr(cast({getExp(operandExp)} as char), 1, 1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as datetime)"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))"; case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))"; case "System.Int16": @@ -60,7 +60,7 @@ namespace FreeSql.Odbc.MySql case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as unsigned)"; case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as char), 1, 1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as datetime)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))"; case "System.Int16": @@ -399,10 +399,10 @@ namespace FreeSql.Odbc.MySql var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; } } else @@ -535,7 +535,7 @@ namespace FreeSql.Odbc.MySql case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as unsigned)"; case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as char), 1, 1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))"; case "ToInt16": diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlUtils.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlUtils.cs index 95d80ad4..0ec715b9 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlUtils.cs @@ -18,10 +18,10 @@ namespace FreeSql.Odbc.MySql public override DbParameter AppendParamter(List _params, string parameterName, ColumnInfo col, Type type, object value) { if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; - var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), Value = value }; + var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName) }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; - if (tp != null) - ret.OdbcType = (OdbcType)tp.Value; + if (tp != null) ret.OdbcType = (OdbcType)tp.Value; + ret.Value = value; _params?.Add(ret); return ret; } @@ -29,10 +29,10 @@ namespace FreeSql.Odbc.MySql public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => Utils.GetDbParamtersByObject(sql, obj, null, (name, type, value) => { - var ret = new OdbcParameter { ParameterName = $"?{name}", Value = value }; + var ret = new OdbcParameter { ParameterName = $"?{name}" }; var tp = _orm.CodeFirst.GetDbInfo(type)?.type; - if (tp != null) - ret.OdbcType = (OdbcType)tp.Value; + if (tp != null) ret.OdbcType = (OdbcType)tp.Value; + ret.Value = value; return ret; }); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleDelete.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleDelete.cs index a5e87939..b5ceafe7 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.Odbc.Oracle { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Odbc.Oracle 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Odbc.Oracle 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs index 731ad1c7..750ec905 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.Odbc.Oracle .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleUpdate.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleUpdate.cs index dfe73589..b758277b 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleUpdate.cs @@ -22,11 +22,7 @@ namespace FreeSql.Odbc.Oracle public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Odbc.Oracle 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -72,10 +68,7 @@ namespace FreeSql.Odbc.Oracle public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Odbc.Oracle 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleUtils.cs b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleUtils.cs index 7ee2273d..d8859e15 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/OdbcOracleUtils.cs @@ -36,7 +36,9 @@ namespace FreeSql.Odbc.Oracle value = string.Concat(value); break; } - var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName), OdbcType = dbtype ?? default, Value = value }; + var ret = new OdbcParameter { ParameterName = QuoteParamterName(parameterName) }; + if (dbtype != null) ret.OdbcType = dbtype.Value; + ret.Value = value; _params?.Add(ret); return ret; } @@ -62,7 +64,9 @@ namespace FreeSql.Odbc.Oracle value = string.Concat(value); break; } - var ret = new OdbcParameter { ParameterName = $":{name}", OdbcType = dbtype ?? default, Value = value }; + var ret = new OdbcParameter { ParameterName = $":{name}" }; + if (dbtype != null) ret.OdbcType = dbtype.Value; + ret.Value = value; return ret; }); diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLDelete.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLDelete.cs index 72267df3..b83cc626 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.Odbc.PostgreSQL public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.Odbc.PostgreSQL #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs index 8f438e22..e6bdc6a4 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs @@ -35,6 +35,7 @@ namespace FreeSql.Odbc.PostgreSQL .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLUpdate.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLUpdate.cs index e9f402d2..3900e6ad 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -32,40 +33,48 @@ namespace FreeSql.Odbc.PostgreSQL protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -129,40 +138,48 @@ namespace FreeSql.Odbc.PostgreSQL async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs index 4a20a567..d9dedb29 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/OdbcPostgreSQLExpression.cs @@ -35,7 +35,7 @@ namespace FreeSql.Odbc.PostgreSQL case "System.Boolean": return $"(({getExp(operandExp)})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(operandExp)})::int2"; case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(operandExp)})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"({getExp(operandExp)})::timestamp"; case "System.Decimal": return $"({getExp(operandExp)})::numeric"; case "System.Double": return $"({getExp(operandExp)})::float8"; case "System.Int16": return $"({getExp(operandExp)})::int2"; @@ -63,7 +63,7 @@ namespace FreeSql.Odbc.PostgreSQL case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2"; case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"({getExp(callExp.Arguments[0])})::timestamp"; case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric"; case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8"; case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2"; @@ -493,10 +493,10 @@ namespace FreeSql.Odbc.PostgreSQL var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})::int8%4=0 AND ({isLeapYearArgs1})::int8%100<>0 OR ({isLeapYearArgs1})::int8%400=0)"; - case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; } } else @@ -630,7 +630,7 @@ namespace FreeSql.Odbc.PostgreSQL case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "ToByte": return $"({getExp(exp.Arguments[0])})::int2"; case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)"; - case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric"; case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8"; case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2"; diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerDelete.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerDelete.cs index f7238b32..e0f184e5 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerDelete.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,45 +19,56 @@ namespace FreeSql.Odbc.SqlServer public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" WHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" WHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -64,45 +76,56 @@ namespace FreeSql.Odbc.SqlServer #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" WHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" WHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs index 0132502c..064eccb4 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs @@ -66,6 +66,7 @@ namespace FreeSql.Odbc.SqlServer .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerUpdate.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerUpdate.cs index a7baf1ca..d1a74591 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -24,45 +25,54 @@ namespace FreeSql.Odbc.SqlServer protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" \r\nWHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" \r\nWHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -108,45 +118,54 @@ namespace FreeSql.Odbc.SqlServer async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" \r\nWHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" \r\nWHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index e19d4fa5..ebafc373 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -32,7 +32,7 @@ namespace FreeSql.Odbc.SqlServer case "System.Boolean": return $"(cast({getExp(operandExp)} as varchar) not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as tinyint)"; case "System.Char": return $"substring(cast({getExp(operandExp)} as nvarchar),1,1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as datetime)"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))"; case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))"; case "System.Int16": return $"cast({getExp(operandExp)} as smallint)"; @@ -63,7 +63,7 @@ namespace FreeSql.Odbc.SqlServer case "System.Boolean": return $"(cast({getExp(callExp.Arguments[0])} as varchar) not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as tinyint)"; case "System.Char": return $"substring(cast({getExp(callExp.Arguments[0])} as nvarchar),1,1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as datetime)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))"; case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as smallint)"; @@ -400,10 +400,10 @@ namespace FreeSql.Odbc.SqlServer var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; } } else @@ -526,7 +526,7 @@ namespace FreeSql.Odbc.SqlServer case "ToBoolean": return $"(cast({getExp(exp.Arguments[0])} as varchar) not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)"; case "ToChar": return $"substring(cast({getExp(exp.Arguments[0])} as nvarchar),1,1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))"; case "ToInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)"; diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleDelete.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleDelete.cs index 618819b8..c3f7203d 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleDelete.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.Oracle.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.Oracle 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Oracle 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs index f569f89a..00c611ea 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.Oracle.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleUpdate.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleUpdate.cs index 0aaa87f6..f180ded1 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleUpdate.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleUpdate.cs @@ -22,11 +22,7 @@ namespace FreeSql.Oracle.Curd public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.Oracle 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -72,10 +68,7 @@ namespace FreeSql.Oracle.Curd public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Oracle 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj index 8287e388..1637f7fc 100644 --- a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj +++ b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 Oracle 11 diff --git a/Providers/FreeSql.Provider.Oracle/OracleUtils.cs b/Providers/FreeSql.Provider.Oracle/OracleUtils.cs index 728a6740..3e286782 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleUtils.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleUtils.cs @@ -25,8 +25,9 @@ namespace FreeSql.Oracle else value = (bool)value == true ? 1 : 0; dbtype = OracleDbType.Int16; } - var ret = new OracleParameter { ParameterName = QuoteParamterName(parameterName), Value = value }; + var ret = new OracleParameter { ParameterName = QuoteParamterName(parameterName) }; if (dbtype != null) ret.OracleDbType = dbtype.Value; + ret.Value = value; if (col != null) { var dbtype2 = (OracleDbType)_orm.DbFirst.GetDbType(new DatabaseModel.DbColumnInfo { DbTypeTextFull = col.Attribute.DbType?.Replace("NOT NULL", "").Replace(" NULL", "").Trim(), DbTypeText = col.DbTypeText }); @@ -63,8 +64,9 @@ namespace FreeSql.Oracle else value = (bool)value == true ? 1 : 0; dbtype = OracleDbType.Int16; } - var ret = new OracleParameter { ParameterName = $":{name}", Value = value }; + var ret = new OracleParameter { ParameterName = $":{name}" }; if (dbtype != null) ret.OracleDbType = dbtype.Value; + ret.Value = value; return ret; }); diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLDelete.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLDelete.cs index c4c60837..2ed402c9 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLDelete.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.PostgreSQL.Curd public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.PostgreSQL.Curd #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs index 6d5a6291..4096e713 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs @@ -35,6 +35,7 @@ namespace FreeSql.PostgreSQL.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; insert._noneParameterFlag = flagInsert ? "cuc" : "cu"; string sql = ""; diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLUpdate.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLUpdate.cs index 0d7ad243..03b9dcd2 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLUpdate.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -32,40 +33,48 @@ namespace FreeSql.PostgreSQL.Curd protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -129,40 +138,48 @@ namespace FreeSql.PostgreSQL.Curd async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj index 50791ab6..db59f51f 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj +++ b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj @@ -2,7 +2,7 @@ netstandard2.0;net461;net452;net451;net45 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 PostgreSQL 9.5 diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs index 2cd6d007..dedd5ef3 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLExpression.cs @@ -36,7 +36,7 @@ namespace FreeSql.PostgreSQL case "System.Boolean": return $"(({getExp(operandExp)})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(operandExp)})::int2"; case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(operandExp)})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"({getExp(operandExp)})::timestamp"; case "System.Decimal": return $"({getExp(operandExp)})::numeric"; case "System.Double": return $"({getExp(operandExp)})::float8"; case "System.Int16": return $"({getExp(operandExp)})::int2"; @@ -64,7 +64,7 @@ namespace FreeSql.PostgreSQL case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2"; case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"({getExp(callExp.Arguments[0])})::timestamp"; case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric"; case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8"; case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2"; @@ -524,10 +524,10 @@ namespace FreeSql.PostgreSQL var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})::int8%4=0 AND ({isLeapYearArgs1})::int8%100<>0 OR ({isLeapYearArgs1})::int8%400=0)"; - case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; } } else @@ -661,7 +661,7 @@ namespace FreeSql.PostgreSQL case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::varchar not in ('0','false','f','no'))"; case "ToByte": return $"({getExp(exp.Arguments[0])})::int2"; case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)"; - case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric"; case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8"; case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2"; diff --git a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongDelete.cs b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongDelete.cs index 5b30f6c0..dcaf61fa 100644 --- a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongDelete.cs +++ b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,40 +19,50 @@ namespace FreeSql.ShenTong.Curd public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -59,40 +70,50 @@ namespace FreeSql.ShenTong.Curd #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw ex; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs index 47a7f022..e254523f 100644 --- a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongInsertOrUpdate.cs @@ -62,6 +62,7 @@ namespace FreeSql.ShenTong.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongUpdate.cs b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongUpdate.cs index 11bddb24..72a36649 100644 --- a/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongUpdate.cs +++ b/Providers/FreeSql.Provider.ShenTong/Curd/ShenTongUpdate.cs @@ -4,6 +4,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -33,40 +34,48 @@ namespace FreeSql.ShenTong.Curd protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -130,40 +139,48 @@ namespace FreeSql.ShenTong.Curd async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(sql).Append(" RETURNING "); - - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw ex; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" RETURNING "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.Append(sbret).ToString(); + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj b/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj index a0a53d57..4803e309 100644 --- a/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj +++ b/Providers/FreeSql.Provider.ShenTong/FreeSql.Provider.ShenTong.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 神舟通用数据库 7.0.8 diff --git a/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs b/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs index d1bd1916..70d9c334 100644 --- a/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs +++ b/Providers/FreeSql.Provider.ShenTong/ShenTongExpression.cs @@ -35,7 +35,7 @@ namespace FreeSql.ShenTong case "System.Boolean": return $"(({getExp(operandExp)})::text not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(operandExp)})::int2"; case "System.Char": return $"substr(({getExp(operandExp)})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(operandExp)})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"({getExp(operandExp)})::timestamp"; case "System.Decimal": return $"({getExp(operandExp)})::numeric"; case "System.Double": return $"({getExp(operandExp)})::float8"; case "System.Int16": return $"({getExp(operandExp)})::int2"; @@ -63,7 +63,7 @@ namespace FreeSql.ShenTong case "System.Boolean": return $"(({getExp(callExp.Arguments[0])})::text not in ('0','false','f','no'))"; case "System.Byte": return $"({getExp(callExp.Arguments[0])})::int2"; case "System.Char": return $"substr(({getExp(callExp.Arguments[0])})::char, 1, 1)"; - case "System.DateTime": return $"({getExp(callExp.Arguments[0])})::timestamp"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"({getExp(callExp.Arguments[0])})::timestamp"; case "System.Decimal": return $"({getExp(callExp.Arguments[0])})::numeric"; case "System.Double": return $"({getExp(callExp.Arguments[0])})::float8"; case "System.Int16": return $"({getExp(callExp.Arguments[0])})::int2"; @@ -448,10 +448,10 @@ namespace FreeSql.ShenTong var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; } } else @@ -585,7 +585,7 @@ namespace FreeSql.ShenTong case "ToBoolean": return $"(({getExp(exp.Arguments[0])})::text not in ('0','false','f','no'))"; case "ToByte": return $"({getExp(exp.Arguments[0])})::int2"; case "ToChar": return $"substr(({getExp(exp.Arguments[0])})::char, 1, 1)"; - case "ToDateTime": return $"({getExp(exp.Arguments[0])})::timestamp"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"({getExp(exp.Arguments[0])})::timestamp"; case "ToDecimal": return $"({getExp(exp.Arguments[0])})::numeric"; case "ToDouble": return $"({getExp(exp.Arguments[0])})::float8"; case "ToInt16": return $"({getExp(exp.Arguments[0])})::int2"; diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerDelete.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerDelete.cs index 61e386ab..05ae3498 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerDelete.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerDelete.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -18,45 +19,56 @@ namespace FreeSql.SqlServer.Curd public override List ExecuteDeleted() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" WHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" WHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(_orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } @@ -64,45 +76,56 @@ namespace FreeSql.SqlServer.Curd #else async public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" WHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - } - catch (Exception ex) + if (dbParms == null) + { + dbParms = _params.ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"DELETED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" WHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Delete, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + ret.AddRange(await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken)); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + if (dbParms != null) { - exception = ex; - throw; + this.ClearData(); + sbret.Clear(); } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } - this.ClearData(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs index f672ded9..159c650b 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs @@ -66,6 +66,7 @@ namespace FreeSql.SqlServer.Curd .WithTransaction(_transaction) .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._source = data; + insert._table = _table; var sql = insert.ToSql(); if (string.IsNullOrEmpty(sql)) return null; if (insert._params?.Any() == true) dbParams.AddRange(insert._params); diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerUpdate.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerUpdate.cs index c63178cd..4d6fb211 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerUpdate.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerUpdate.cs @@ -3,6 +3,7 @@ using FreeSql.Internal.Model; using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Linq; using System.Text; using System.Threading; @@ -25,45 +26,54 @@ namespace FreeSql.SqlServer.Curd protected override List RawExecuteUpdated() { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" \r\nWHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + ToSqlFetch(sb => { - ret = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" \r\nWHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = _orm.Ado.Query(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } @@ -109,45 +119,54 @@ namespace FreeSql.SqlServer.Curd async protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) { - var sql = this.ToSql(); - if (string.IsNullOrEmpty(sql)) return new List(); - - var sb = new StringBuilder(); - sb.Append(" OUTPUT "); - var colidx = 0; - foreach (var col in _table.Columns.Values) - { - if (colidx > 0) sb.Append(", "); - sb.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); - ++colidx; - } - - var validx = sql.IndexOf(" \r\nWHERE "); - if (validx == -1) throw new ArgumentException("找不到 WHERE "); - sb.Insert(0, sql.Substring(0, validx)); - sb.Append(sql.Substring(validx)); - - sql = sb.ToString(); - var dbParms = _params.Concat(_paramsSource).ToArray(); - var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); - _orm.Aop.CurdBeforeHandler?.Invoke(this, before); var ret = new List(); - Exception exception = null; - try + DbParameter[] dbParms = null; + StringBuilder sbret = null; + await ToSqlFetchAsync(async sb => { - ret = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); - ValidateVersionAndThrow(ret.Count, sql, dbParms); - } - catch (Exception ex) - { - exception = ex; - throw; - } - finally - { - var after = new Aop.CurdAfterEventArgs(before, exception, ret); - _orm.Aop.CurdAfterHandler?.Invoke(this, after); - } + if (dbParms == null) + { + dbParms = _params.Concat(_paramsSource).ToArray(); + sbret = new StringBuilder(); + sbret.Append(" OUTPUT "); + + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (colidx > 0) sbret.Append(", "); + sbret.Append(_commonUtils.RereadColumn(col, $"INSERTED.{_commonUtils.QuoteSqlName(col.Attribute.Name)}")).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName)); + ++colidx; + } + } + var sql = sb.ToString(); + var validx = sql.IndexOf(" \r\nWHERE "); + if (validx == -1) throw new ArgumentException("找不到 WHERE "); + sql = sb.Clear().Append(sql.Substring(0, validx)) + .Append(sbret) + .Append(sql.Substring(validx)).ToString(); + + var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Update, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + + Exception exception = null; + try + { + var rettmp = await _orm.Ado.QueryAsync(_table.TypeLazy ?? _table.Type, _connection, _transaction, CommandType.Text, sql, _commandTimeout, dbParms, cancellationToken); + ValidateVersionAndThrow(rettmp.Count, sql, dbParms); + ret.AddRange(rettmp); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + }); + sbret?.Clear(); return ret; } #endif diff --git a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj index dac06b77..bf8bfc27 100644 --- a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj +++ b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;net451;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 SqlServer 2005+,并根据版本适配分页方法:row_number 或 offset fetch next diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index 790d2edd..a0b80ab8 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -32,7 +32,7 @@ namespace FreeSql.SqlServer case "System.Boolean": return $"(cast({getExp(operandExp)} as varchar) not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as tinyint)"; case "System.Char": return $"substring(cast({getExp(operandExp)} as nvarchar),1,1)"; - case "System.DateTime": return $"cast({getExp(operandExp)} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as datetime)"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))"; case "System.Double": return $"cast({getExp(operandExp)} as decimal(32,16))"; case "System.Int16": return $"cast({getExp(operandExp)} as smallint)"; @@ -62,7 +62,7 @@ namespace FreeSql.SqlServer case "System.Boolean": return $"(cast({getExp(callExp.Arguments[0])} as varchar) not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as tinyint)"; case "System.Char": return $"substring(cast({getExp(callExp.Arguments[0])} as nvarchar),1,1)"; - case "System.DateTime": return $"cast({getExp(callExp.Arguments[0])} as datetime)"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as datetime)"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as decimal(32,16))"; case "System.Int16": return $"cast({getExp(callExp.Arguments[0])} as smallint)"; @@ -400,10 +400,10 @@ namespace FreeSql.SqlServer var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; } } else @@ -524,7 +524,7 @@ namespace FreeSql.SqlServer case "ToBoolean": return $"(cast({getExp(exp.Arguments[0])} as varchar) not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)"; case "ToChar": return $"substring(cast({getExp(exp.Arguments[0])} as nvarchar),1,1)"; - case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"cast({getExp(exp.Arguments[0])} as datetime)"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))"; case "ToInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)"; diff --git a/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj b/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj index e9e77167..748d6f6f 100644 --- a/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj +++ b/Providers/FreeSql.Provider.SqlServerForSystem/FreeSql.Provider.SqlServerForSystem.csproj @@ -2,7 +2,7 @@ netstandard2.0;net60;net50;net451;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 System.Data.SqlClient + SqlServer 2005+,并根据版本适配分页方法:row_number 或 offset fetch next diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteDelete.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteDelete.cs index 3a108707..0e46d437 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteDelete.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteDelete.cs @@ -16,17 +16,11 @@ namespace FreeSql.Sqlite.Curd { } - public override List ExecuteDeleted() - { - throw new NotImplementedException(); - } + public override List ExecuteDeleted() => throw new NotImplementedException("FreeSql.Provider.Sqlite 未实现该功能"); #if net40 #else - public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public override Task> ExecuteDeletedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Sqlite 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs index b6b4422e..bb2836a2 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs @@ -37,6 +37,7 @@ namespace FreeSql.Sqlite.Curd .NoneParameter(true) as Internal.CommonProvider.InsertProvider; insert._noneParameterFlag = flagInsert ? "c" : "cu"; insert._source = data; + insert._table = _table; string sql = ""; if (IdentityColumn != null && flagInsert) sql = insert.ToSql(); diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteUpdate.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteUpdate.cs index 6bde5519..e88cf832 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteUpdate.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteUpdate.cs @@ -22,11 +22,7 @@ namespace FreeSql.Sqlite.Curd public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); - - protected override List RawExecuteUpdated() - { - throw new NotImplementedException(); - } + protected override List RawExecuteUpdated() => throw new NotImplementedException("FreeSql.Provider.Sqlite 未实现该功能"); protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) { @@ -70,10 +66,7 @@ namespace FreeSql.Sqlite.Curd public override Task ExecuteAffrowsAsync(CancellationToken cancellationToken = default) => base.SplitExecuteAffrowsAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); public override Task> ExecuteUpdatedAsync(CancellationToken cancellationToken = default) => base.SplitExecuteUpdatedAsync(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999, cancellationToken); - protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + protected override Task> RawExecuteUpdatedAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException("FreeSql.Provider.Sqlite 未实现该功能"); #endif } } diff --git a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj index 4177b66d..c8466939 100644 --- a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj +++ b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45;net40 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 Sqlite 3.0,支持 .NetCore、.NetFramework、Xamarin diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs index 3192c89a..879b6bc3 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs @@ -32,7 +32,7 @@ namespace FreeSql.Sqlite case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(operandExp)} as int2)"; case "System.Char": return $"substr(cast({getExp(operandExp)} as character), 1, 1)"; - case "System.DateTime": return $"datetime({getExp(operandExp)})"; + case "System.DateTime": return ExpressionConstDateTime(operandExp) ?? $"datetime({getExp(operandExp)})"; case "System.Decimal": return $"cast({getExp(operandExp)} as decimal(36,18))"; case "System.Double": return $"cast({getExp(operandExp)} as double)"; case "System.Int16": @@ -60,7 +60,7 @@ namespace FreeSql.Sqlite case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as int2)"; case "System.Char": return $"substr(cast({getExp(callExp.Arguments[0])} as character), 1, 1)"; - case "System.DateTime": return $"datetime({getExp(callExp.Arguments[0])})"; + case "System.DateTime": return ExpressionConstDateTime(callExp.Arguments[0]) ?? $"datetime({getExp(callExp.Arguments[0])})"; case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as decimal(36,18))"; case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as double)"; case "System.Int16": @@ -416,10 +416,10 @@ namespace FreeSql.Sqlite var isLeapYearArgs1 = getExp(exp.Arguments[0]); return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)"; - case "Parse": return $"datetime({getExp(exp.Arguments[0])})"; + case "Parse": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"datetime({getExp(exp.Arguments[0])})"; case "ParseExact": case "TryParse": - case "TryParseExact": return $"datetime({getExp(exp.Arguments[0])})"; + case "TryParseExact": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"datetime({getExp(exp.Arguments[0])})"; } } else @@ -552,7 +552,7 @@ namespace FreeSql.Sqlite case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; case "ToByte": return $"cast({getExp(exp.Arguments[0])} as int2)"; case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as character), 1, 1)"; - case "ToDateTime": return $"datetime({getExp(exp.Arguments[0])})"; + case "ToDateTime": return ExpressionConstDateTime(exp.Arguments[0]) ?? $"datetime({getExp(exp.Arguments[0])})"; case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))"; case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as double)"; case "ToInt16": diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteUtils.cs b/Providers/FreeSql.Provider.Sqlite/SqliteUtils.cs index 3cd4c2d9..4e036627 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteUtils.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteUtils.cs @@ -43,7 +43,7 @@ namespace FreeSql.Sqlite var ret = new SQLiteParameter(); #endif ret.ParameterName = QuoteParamterName(parameterName); - ret.DbType = dbtype ?? default; + if (dbtype != null) ret.DbType = dbtype.Value; ret.Value = value; _params?.Add(ret); return ret; diff --git a/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj b/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj index d2ea2d60..e9a158c4 100644 --- a/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj +++ b/Providers/FreeSql.Provider.SqliteCore/FreeSql.Provider.SqliteCore.csproj @@ -2,7 +2,7 @@ netstandard2.0;net6.0 - 3.2.301 + 3.2.500 true FreeSql;ncc;YeXiangQin FreeSql 数据库实现,基于 Microsoft.Data.Sqlite.Core、Sqlite 3.0,支持 .netstandard2.0、.net6.0