From 511d8f909a6e27408b69b1b5e16420f2b2aa551d Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Sat, 23 May 2020 18:17:54 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=E6=9C=AA=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E7=9A=84=E5=8A=9F=E8=83=BD=20IFreeSql.InsertOrUpdate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql.DbContext/FreeSql.DbContext.xml | 18 --- .../Curd/MySqlInsertOrUpdateTest.cs | 87 +++++++++++ .../Dameng/Curd/DamengInsertOrUpdateTest.cs | 143 +++++++++++++++++ .../MySql/Curd/MySqlInsertOrUpdateTest.cs | 87 +++++++++++ .../Oracle/Curd/OracleInsertOrUpdateTest.cs | 144 ++++++++++++++++++ .../Curd/PostgreSQLInsertOrUpdateTest.cs | 87 +++++++++++ .../Curd/SqlServerInsertOrUpdateTest.cs | 141 +++++++++++++++++ .../Dameng/Curd/DamengInsertOrUpdateTest.cs | 144 ++++++++++++++++++ .../MySql/Curd/MySqlInsertOrUpdateTest.cs | 87 +++++++++++ .../Oracle/Curd/OracleInsertOrUpdateTest.cs | 144 ++++++++++++++++++ .../Curd/PostgreSQLInsertOrUpdateTest.cs | 87 +++++++++++ .../Curd/SqlServerInsertOrUpdateTest.cs | 141 +++++++++++++++++ .../Sqlite/Curd/SqliteInsertOrUpdateTest.cs | 76 +++++++++ FreeSql/FreeSql.xml | 8 + .../CommonProvider/InsertOrUpdateProvider.cs | 134 +++++++++++++++- .../Curd/DamengInsertOrUpdate.cs | 64 +++++--- .../Curd/MySqlInsertOrUpdate.cs | 39 +++-- .../Dameng/Curd/OdbcDamengInsertOrUpdate.cs | 64 +++++--- .../MySql/Curd/OdbcMySqlInsertOrUpdate.cs | 37 +++-- .../Oracle/Curd/OdbcOracleInsertOrUpdate.cs | 64 +++++--- .../Curd/OdbcPostgreSQLInsertOrUpdate.cs | 48 ++++-- .../Curd/OdbcSqlServerInsertOrUpdate.cs | 67 +++++--- .../Curd/OracleInsertOrUpdate.cs | 64 +++++--- .../Curd/PostgreSQLInsertOrUpdate.cs | 48 ++++-- .../Curd/SqlServerInsertOrUpdate.cs | 67 +++++--- .../Curd/SqliteInsertOrUpdate.cs | 42 +++-- 26 files changed, 1948 insertions(+), 184 deletions(-) diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 13ddf83b..132d875e 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -125,13 +125,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 @@ -488,14 +481,3 @@ -Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])"> - - 批量注入 Repository,可以参考代码自行调整 - - - - - - - - diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertOrUpdateTest.cs index 6198c553..91b56e34 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlInsertOrUpdateTest.cs @@ -57,6 +57,93 @@ ON DUPLICATE KEY UPDATE public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '011') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(2, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(2, '02') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(5, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`) + +; + +INSERT INTO `tbiou022`(`name`) VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(12, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengInsertOrUpdateTest.cs index e3832aaa..3901c553 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengInsertOrUpdateTest.cs @@ -154,6 +154,149 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '011' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 2 as ID, '02' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual +UNION ALL + SELECT 2, '02' FROM dual +UNION ALL + SELECT 3, '03' FROM dual +UNION ALL + SELECT 4, '04' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '001' as NAME FROM dual +UNION ALL + SELECT 2, '002' FROM dual +UNION ALL + SELECT 3, '003' FROM dual +UNION ALL + SELECT 4, '004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('01')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('011')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('02')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('01') +INTO ""TBIOU022""(""NAME"") VALUES('02') +INTO ""TBIOU022""(""NAME"") VALUES('03') +INTO ""TBIOU022""(""NAME"") VALUES('04') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('001') +INTO ""TBIOU022""(""NAME"") VALUES('002') +INTO ""TBIOU022""(""NAME"") VALUES('003') +INTO ""TBIOU022""(""NAME"") VALUES('004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '100001' as NAME FROM dual +UNION ALL + SELECT 2, '100002' FROM dual +UNION ALL + SELECT 3, '100003' FROM dual +UNION ALL + SELECT 4, '100004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME) + +; + +INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('00001') +INTO ""TBIOU022""(""NAME"") VALUES('00002') +INTO ""TBIOU022""(""NAME"") VALUES('00003') +INTO ""TBIOU022""(""NAME"") VALUES('00004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertOrUpdateTest.cs index 3b9fc212..283e8e75 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlInsertOrUpdateTest.cs @@ -57,6 +57,93 @@ ON DUPLICATE KEY UPDATE public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '011') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(2, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(2, '02') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`) + +; + +INSERT INTO `tbiou022`(`name`) VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(12, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleInsertOrUpdateTest.cs index 156bebbf..8ed896b3 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleInsertOrUpdateTest.cs @@ -154,6 +154,150 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '011' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 2 as ID, '02' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual +UNION ALL + SELECT 2, '02' FROM dual +UNION ALL + SELECT 3, '03' FROM dual +UNION ALL + SELECT 4, '04' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '001' as NAME FROM dual +UNION ALL + SELECT 2, '002' FROM dual +UNION ALL + SELECT 3, '003' FROM dual +UNION ALL + SELECT 4, '004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('01')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('011')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('02')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('01') +INTO ""TBIOU022""(""NAME"") VALUES('02') +INTO ""TBIOU022""(""NAME"") VALUES('03') +INTO ""TBIOU022""(""NAME"") VALUES('04') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('001') +INTO ""TBIOU022""(""NAME"") VALUES('002') +INTO ""TBIOU022""(""NAME"") VALUES('003') +INTO ""TBIOU022""(""NAME"") VALUES('004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '100001' as NAME FROM dual +UNION ALL + SELECT 2, '100002' FROM dual +UNION ALL + SELECT 3, '100003' FROM dual +UNION ALL + SELECT 4, '100004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME) + +; + +INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('00001') +INTO ""TBIOU022""(""NAME"") VALUES('00002') +INTO ""TBIOU022""(""NAME"") VALUES('00003') +INTO ""TBIOU022""(""NAME"") VALUES('00004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs index 90ce4b5b..e539b712 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs @@ -95,6 +95,93 @@ ON CONFLICT(""id"") DO UPDATE SET public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '011') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(2, '02') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name"" + +; + +INSERT INTO ""tbiou022""(""name"") VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs index 0c00dbb5..90bc5604 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs @@ -154,6 +154,147 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'01' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'011' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 2 as id, N'02' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'01' as name +UNION ALL + SELECT 2, N'02' +UNION ALL + SELECT 3, N'03' +UNION ALL + SELECT 4, N'04' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'001' as name +UNION ALL + SELECT 2, N'002' +UNION ALL + SELECT 3, N'003' +UNION ALL + SELECT 4, N'004' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'01'), (N'02'), (N'03'), (N'04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'001'), (N'002'), (N'003'), (N'004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'100001' as name +UNION ALL + SELECT 2, N'100002' +UNION ALL + SELECT 3, N'100003' +UNION ALL + SELECT 4, N'100004' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF; + +; + +INSERT INTO [tbiou022]([name]) VALUES(N'00001'), (N'00002'), (N'00003'), (N'00004')", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertOrUpdateTest.cs index 54e4c38a..3a4ceb48 100644 --- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertOrUpdateTest.cs @@ -154,6 +154,150 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '011' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 2 as ID, '02' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual +UNION ALL + SELECT 2, '02' FROM dual +UNION ALL + SELECT 3, '03' FROM dual +UNION ALL + SELECT 4, '04' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '001' as NAME FROM dual +UNION ALL + SELECT 2, '002' FROM dual +UNION ALL + SELECT 3, '003' FROM dual +UNION ALL + SELECT 4, '004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + iou.ExecuteAffrows(); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('01')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('011')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('02')", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('01') +INTO ""TBIOU022""(""NAME"") VALUES('02') +INTO ""TBIOU022""(""NAME"") VALUES('03') +INTO ""TBIOU022""(""NAME"") VALUES('04') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('001') +INTO ""TBIOU022""(""NAME"") VALUES('002') +INTO ""TBIOU022""(""NAME"") VALUES('003') +INTO ""TBIOU022""(""NAME"") VALUES('004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '100001' as NAME FROM dual +UNION ALL + SELECT 2, '100002' FROM dual +UNION ALL + SELECT 3, '100003' FROM dual +UNION ALL + SELECT 4, '100004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME) + +; + +INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('00001') +INTO ""TBIOU022""(""NAME"") VALUES('00002') +INTO ""TBIOU022""(""NAME"") VALUES('00003') +INTO ""TBIOU022""(""NAME"") VALUES('00004') + SELECT 1 FROM DUAL", sql); + iou.ExecuteAffrows(); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlInsertOrUpdateTest.cs index 3cfe1a62..471920c9 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlInsertOrUpdateTest.cs @@ -57,6 +57,93 @@ ON DUPLICATE KEY UPDATE public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '011') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(2, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(2, '02') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(5, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`)", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`name`) VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO `tbiou022`(`id`, `name`) VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`) + +; + +INSERT INTO `tbiou022`(`name`) VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(12, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleInsertOrUpdateTest.cs index e645b7fc..d383cea5 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleInsertOrUpdateTest.cs @@ -154,6 +154,150 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '011' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 2 as ID, '02' as NAME FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '01' as NAME FROM dual +UNION ALL + SELECT 2, '02' FROM dual +UNION ALL + SELECT 3, '03' FROM dual +UNION ALL + SELECT 4, '04' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '001' as NAME FROM dual +UNION ALL + SELECT 2, '002' FROM dual +UNION ALL + SELECT 3, '003' FROM dual +UNION ALL + SELECT 4, '004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME)", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""TBIOU022""(""NAME"") VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('01') +INTO ""TBIOU022""(""NAME"") VALUES('02') +INTO ""TBIOU022""(""NAME"") VALUES('03') +INTO ""TBIOU022""(""NAME"") VALUES('04') + SELECT 1 FROM DUAL", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('001') +INTO ""TBIOU022""(""NAME"") VALUES('002') +INTO ""TBIOU022""(""NAME"") VALUES('003') +INTO ""TBIOU022""(""NAME"") VALUES('004') + SELECT 1 FROM DUAL", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"MERGE INTO ""TBIOU022"" t1 +USING (SELECT 1 as ID, '100001' as NAME FROM dual +UNION ALL + SELECT 2, '100002' FROM dual +UNION ALL + SELECT 3, '100003' FROM dual +UNION ALL + SELECT 4, '100004' FROM dual ) t2 ON (t1.""ID"" = t2.ID) +WHEN MATCHED THEN + update set ""NAME"" = t2.NAME +WHEN NOT MATCHED THEN + insert (""ID"", ""NAME"") + values (t2.ID, t2.NAME) + +; + +INSERT ALL +INTO ""TBIOU022""(""NAME"") VALUES('00001') +INTO ""TBIOU022""(""NAME"") VALUES('00002') +INTO ""TBIOU022""(""NAME"") VALUES('00003') +INTO ""TBIOU022""(""NAME"") VALUES('00004') + SELECT 1 FROM DUAL", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + //Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs index 1b1e853b..4049b04d 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertOrUpdateTest.cs @@ -95,6 +95,93 @@ ON CONFLICT(""id"") DO UPDATE SET public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '011') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(2, '02') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name""", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""id"", ""name"") VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') +ON CONFLICT(""id"") DO UPDATE SET +""name"" = EXCLUDED.""name"" + +; + +INSERT INTO ""tbiou022""(""name"") VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs index 7858a27d..dcbb2a3b 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerInsertOrUpdateTest.cs @@ -156,6 +156,147 @@ WHEN NOT MATCHED THEN public int id { get; set; } public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'01' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'011' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 2 as id, N'02' as name ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'01' as name +UNION ALL + SELECT 2, N'02' +UNION ALL + SELECT 3, N'03' +UNION ALL + SELECT 4, N'04' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'001' as name +UNION ALL + SELECT 2, N'002' +UNION ALL + SELECT 3, N'003' +UNION ALL + SELECT 4, N'004' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF;", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'01'), (N'02'), (N'03'), (N'04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO [tbiou022]([name]) VALUES(N'001'), (N'002'), (N'003'), (N'004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"SET IDENTITY_INSERT [tbiou022] ON; +MERGE INTO [tbiou022] t1 +USING (SELECT 1 as id, N'100001' as name +UNION ALL + SELECT 2, N'100002' +UNION ALL + SELECT 3, N'100003' +UNION ALL + SELECT 4, N'100004' ) t2 ON (t1.[id] = t2.id) +WHEN MATCHED THEN + update set [name] = t2.name +WHEN NOT MATCHED THEN + insert ([id], [name]) + values (t2.id, t2.name);; +SET IDENTITY_INSERT [tbiou022] OFF; + +; + +INSERT INTO [tbiou022]([name]) VALUES(N'00001'), (N'00002'), (N'00003'), (N'00004')", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } [Fact] public void InsertOrUpdate_TwoPrimary() diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteInsertOrUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteInsertOrUpdateTest.cs index 0412c2fa..2e793f17 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteInsertOrUpdateTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteInsertOrUpdateTest.cs @@ -81,6 +81,82 @@ namespace FreeSql.Tests.Sqlite public string name { get; set; } } + [Fact] + public void InsertOrUpdate_OnePrimaryAndIdentity() + { + fsql.Delete().Where("1=1").ExecuteAffrows(); + var iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "01" }); + var sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 1, name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(1, '011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { id = 2, name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(2, '02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "01" }, new tbiou022 { id = 2, name = "02" }, new tbiou022 { id = 3, name = "03" }, new tbiou022 { id = 4, name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "001" }, new tbiou022 { id = 2, name = "002" }, new tbiou022 { id = 3, name = "003" }, new tbiou022 { id = 4, name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + var lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count()); + + //--no primary + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "01" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "011" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('011')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new tbiou022 { name = "02" }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('02')", sql); + Assert.Equal(1, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "01" }, new tbiou022 { name = "02" }, new tbiou022 { name = "03" }, new tbiou022 { name = "04" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('01'), ('02'), ('03'), ('04')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { name = "001" }, new tbiou022 { name = "002" }, new tbiou022 { name = "003" }, new tbiou022 { name = "004" } }); + sql = iou.ToSql(); + Assert.Equal(@"INSERT INTO ""tbiou022""(""name"") VALUES('001'), ('002'), ('003'), ('004')", sql); + Assert.Equal(4, iou.ExecuteAffrows()); + + //--no primary and yes + iou = fsql.InsertOrUpdate().SetSource(new[] { new tbiou022 { id = 1, name = "100001" }, new tbiou022 { name = "00001" }, new tbiou022 { id = 2, name = "100002" }, new tbiou022 { name = "00002" }, new tbiou022 { id = 3, name = "100003" }, new tbiou022 { name = "00003" }, new tbiou022 { id = 4, name = "100004" }, new tbiou022 { name = "00004" } }); + sql = iou.ToSql(); + Assert.Equal(@"REPLACE INTO ""tbiou022""(""id"", ""name"") VALUES(1, '100001'), (2, '100002'), (3, '100003'), (4, '100004') + +; + +INSERT INTO ""tbiou022""(""name"") VALUES('00001'), ('00002'), ('00003'), ('00004')", sql); + Assert.Equal(8, iou.ExecuteAffrows()); + lst = fsql.Select().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList(); + Assert.Equal(4, lst.Where(a => a.name == "10000" + a.id).Count()); + } + class tbiou022 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } + [Fact] public void InsertOrUpdate_TwoPrimary() { diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 40b864cc..f4fd5b54 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -2994,6 +2994,13 @@ + + + 如果实体类有自增属性,分成两个 List,有值的Item1 merge,无值的Item2 insert + + + + AsType, Ctor, ClearData 三处地方需要重新加载 @@ -3770,6 +3777,7 @@ Oracle: merge into Sqlite: replace into Dameng: merge into + 注意:还可以使用 FreeSql.Repository 的 InsertOrUpdate 方法 diff --git a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs index 42fe4bee..ba76d54d 100644 --- a/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/InsertOrUpdateProvider.cs @@ -25,6 +25,7 @@ namespace FreeSql.Internal.CommonProvider protected DbParameter[] _params; protected DbTransaction _transaction; protected DbConnection _connection; + public ColumnInfo IdentityColumn { get; } public InsertOrUpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { @@ -33,6 +34,7 @@ namespace FreeSql.Internal.CommonProvider _commonExpression = commonExpression; _table = _commonUtils.GetTableByEntity(typeof(T1)); if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure(); + IdentityColumn = _table.Primarys.Where(a => a.Attribute.IsIdentity).FirstOrDefault(); } protected void ClearData() @@ -130,11 +132,10 @@ namespace FreeSql.Internal.CommonProvider return this; } - public void WriteSourceSelectUnionAll(StringBuilder sb) + public void WriteSourceSelectUnionAll(List source, StringBuilder sb, List dbParams) { - var specialParams = new List(); var didx = 0; - foreach (var d in _source) + foreach (var d in source) { if (didx > 0) sb.Append(" \r\nUNION ALL\r\n "); sb.Append("SELECT "); @@ -147,7 +148,7 @@ namespace FreeSql.Internal.CommonProvider else { object val = col.GetMapValue(d); - sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val)); + sb.Append(_commonUtils.GetNoneParamaterSqlValue(dbParams, col.Attribute.MapType, val)); } if (didx == 0) sb.Append(" as ").Append(col.Attribute.Name); ++colidx2; @@ -163,11 +164,82 @@ namespace FreeSql.Internal.CommonProvider } ++didx; } - if (specialParams.Any()) _params = specialParams.ToArray(); + } + + byte _SplitSourceByIdentityValueIsNullFlag = 0; //防止重复计算 SplitSource + /// + /// 如果实体类有自增属性,分成两个 List,有值的Item1 merge,无值的Item2 insert + /// + /// + /// + public NaviteTuple, List> SplitSourceByIdentityValueIsNull(List source) + { + if (_SplitSourceByIdentityValueIsNullFlag == 1) return NaviteTuple.Create(source, new List()); + if (_SplitSourceByIdentityValueIsNullFlag == 2) return NaviteTuple.Create(new List(), source); + if (IdentityColumn == null) return NaviteTuple.Create(source, new List()); + var ret = NaviteTuple.Create(new List(), new List()); + foreach (var item in source) + { + if (object.Equals(_orm.GetEntityValueWithPropertyName(_table.Type, item, IdentityColumn.CsName), IdentityColumn.CsType.CreateInstanceGetDefaultValue())) + ret.Item2.Add(item); //自增无值的,记录为直接插入 + else + ret.Item1.Add(item); + } + return ret; } public abstract string ToSql(); public int ExecuteAffrows() + { + var affrows = 0; + var ss = SplitSourceByIdentityValueIsNull(_source); + try + { + if (_transaction != null) + { + _source = ss.Item1; + _SplitSourceByIdentityValueIsNullFlag = 1; + affrows += this.RawExecuteAffrows(); + _source = ss.Item2; + _SplitSourceByIdentityValueIsNullFlag = 2; + affrows += this.RawExecuteAffrows(); + } + else + { + using (var conn = _orm.Ado.MasterPool.Get()) + { + _transaction = conn.Value.BeginTransaction(); + var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null); + _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore); + try + { + _source = ss.Item1; + _SplitSourceByIdentityValueIsNullFlag = 1; + affrows += this.RawExecuteAffrows(); + _source = ss.Item2; + _SplitSourceByIdentityValueIsNullFlag = 2; + affrows += this.RawExecuteAffrows(); + _transaction.Commit(); + _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null)); + } + catch (Exception ex) + { + _transaction.Rollback(); + _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex)); + throw ex; + } + _transaction = null; + } + } + } + finally + { + _SplitSourceByIdentityValueIsNullFlag = 0; + ClearData(); + } + return affrows; + } + public int RawExecuteAffrows() { var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return 0; @@ -193,7 +265,7 @@ namespace FreeSql.Internal.CommonProvider } #if net40 #else - async public Task ExecuteAffrowsAsync() + async public Task RawExecuteAffrowsAsync() { var sql = this.ToSql(); if (string.IsNullOrEmpty(sql)) return 0; @@ -217,6 +289,56 @@ namespace FreeSql.Internal.CommonProvider } return affrows; } + async public Task ExecuteAffrowsAsync() + { + var affrows = 0; + var ss = SplitSourceByIdentityValueIsNull(_source); + try + { + if (_transaction != null) + { + _source = ss.Item1; + _SplitSourceByIdentityValueIsNullFlag = 1; + affrows += await this.RawExecuteAffrowsAsync(); + _source = ss.Item2; + _SplitSourceByIdentityValueIsNullFlag = 2; + affrows += await this.RawExecuteAffrowsAsync(); + } + else + { + using (var conn = await _orm.Ado.MasterPool.GetAsync()) + { + _transaction = conn.Value.BeginTransaction(); + var transBefore = new Aop.TraceBeforeEventArgs("BeginTransaction", null); + _orm.Aop.TraceBeforeHandler?.Invoke(this, transBefore); + try + { + _source = ss.Item1; + _SplitSourceByIdentityValueIsNullFlag = 1; + affrows += await this.RawExecuteAffrowsAsync(); + _source = ss.Item2; + _SplitSourceByIdentityValueIsNullFlag = 2; + affrows += await this.RawExecuteAffrowsAsync(); + _transaction.Commit(); + _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "提交", null)); + } + catch (Exception ex) + { + _transaction.Rollback(); + _orm.Aop.TraceAfterHandler?.Invoke(this, new Aop.TraceAfterEventArgs(transBefore, "回滚", ex)); + throw ex; + } + _transaction = null; + } + } + } + finally + { + _SplitSourceByIdentityValueIsNullFlag = 0; + ClearData(); + } + return affrows; + } #endif } } diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs index 52f2e955..ec7370ad 100644 --- a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,54 @@ namespace FreeSql.Dameng.Curd public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") - .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n").Append("USING ("); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - return sb.ToString(); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); + + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs index 6d530b2f..1106945d 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlInsertOrUpdate.cs @@ -1,5 +1,9 @@ using FreeSql.Internal; +using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; +using System.Text; namespace FreeSql.MySql.Curd { @@ -15,15 +19,32 @@ namespace FreeSql.MySql.Curd { if (_source?.Any() != true) return null; - var insert = _orm.Insert() - .AsTable(_tableRule).AsType(_table.Type) - .WithConnection(_connection) - .WithTransaction(_transaction) - .NoneParameter(true) as Internal.CommonProvider.InsertProvider; - insert._source = _source; - var sql = new OnDuplicateKeyUpdate(insert).ToSql(); - _params = insert._params; - return sql; + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getInsertSql(ds.Item1, false); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2, true); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getInsertSql(List data, bool flagInsert) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + + string sql = ""; + if (IdentityColumn != null && flagInsert) sql = insert.ToSql(); + else sql = new OnDuplicateKeyUpdate(insert.InsertIdentity()).ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs index c5826cdc..d36ee50a 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,54 @@ namespace FreeSql.Odbc.Dameng public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") - .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n").Append("USING ("); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - return sb.ToString(); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); + + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs index c8908805..86747427 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/Curd/OdbcMySqlInsertOrUpdate.cs @@ -1,4 +1,6 @@ using FreeSql.Internal; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; namespace FreeSql.Odbc.MySql @@ -15,15 +17,32 @@ namespace FreeSql.Odbc.MySql { if (_source?.Any() != true) return null; - var insert = _orm.Insert() - .AsTable(_tableRule).AsType(_table.Type) - .WithConnection(_connection) - .WithTransaction(_transaction) - .NoneParameter(true) as Internal.CommonProvider.InsertProvider; - insert._source = _source; - var sql = new OdbcMySqlOnDuplicateKeyUpdate(insert).ToSql(); - _params = insert._params; - return sql; + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getInsertSql(ds.Item1, false); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2, true); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getInsertSql(List data, bool flagInsert) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + + string sql = ""; + if (IdentityColumn != null && flagInsert) sql = insert.ToSql(); + else sql = new OdbcMySqlOnDuplicateKeyUpdate(insert.InsertIdentity()).ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs index 0c151cc3..1a0766a1 100644 --- a/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/Oracle/Curd/OdbcOracleInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,54 @@ namespace FreeSql.Odbc.Oracle public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") - .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n").Append("USING ("); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - return sb.ToString(); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); + + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs index ec291e6b..311e46b2 100644 --- a/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/PostgreSQL/Curd/OdbcPostgreSQLInsertOrUpdate.cs @@ -1,4 +1,6 @@ using FreeSql.Internal; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; namespace FreeSql.Odbc.PostgreSQL @@ -15,19 +17,39 @@ namespace FreeSql.Odbc.PostgreSQL { if (_source?.Any() != true) return null; - var insert = _orm.Insert() - .AsTable(_tableRule).AsType(_table.Type) - .WithConnection(_connection) - .WithTransaction(_transaction) - .NoneParameter(true) as Internal.CommonProvider.InsertProvider; - insert._source = _source; - var ocdu = new OdbcPostgreSQLOnConflictDoUpdate(insert); - ocdu.IgnoreColumns(_table.Columns.Values.Where(a => a.Attribute.CanUpdate == false).Select(a => a.Attribute.Name).ToArray()); - if (_table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true).Any() == false) - ocdu.DoNothing(); - var sql = ocdu.ToSql(); - _params = insert._params; - return sql; + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getInsertSql(ds.Item1, false); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2, true); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getInsertSql(List data, bool flagInsert) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + + string sql = ""; + if (IdentityColumn != null && flagInsert) sql = insert.ToSql(); + else + { + var ocdu = new OdbcPostgreSQLOnConflictDoUpdate(insert.InsertIdentity()); + ocdu.IgnoreColumns(_table.Columns.Values.Where(a => a.Attribute.CanUpdate == false).Select(a => a.Attribute.Name).ToArray()); + if (_table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true).Any() == false) + ocdu.DoNothing(); + sql = ocdu.ToSql(); + } + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs index 85f74a23..69b11d78 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/Curd/OdbcSqlServerInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,59 @@ namespace FreeSql.Odbc.SqlServer public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); + + var sb = new StringBuilder(); + if (IdentityColumn != null) sb.Append("SET IDENTITY_INSERT ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" ON;\r\n"); + sb.Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(");"); + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(");"); - return sb.ToString(); + if (IdentityColumn != null) sb.Append(";\r\nSET IDENTITY_INSERT ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" OFF;"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs index 981e33f9..426f1f16 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,54 @@ namespace FreeSql.Oracle.Curd public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") - .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n").Append("USING ("); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - return sb.ToString(); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); + + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(")"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs index 87280563..a8a48263 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLInsertOrUpdate.cs @@ -1,4 +1,6 @@ using FreeSql.Internal; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; namespace FreeSql.PostgreSQL.Curd @@ -15,19 +17,39 @@ namespace FreeSql.PostgreSQL.Curd { if (_source?.Any() != true) return null; - var insert = _orm.Insert() - .AsTable(_tableRule).AsType(_table.Type) - .WithConnection(_connection) - .WithTransaction(_transaction) - .NoneParameter(true) as Internal.CommonProvider.InsertProvider; - insert._source = _source; - var ocdu = new OnConflictDoUpdate(insert); - ocdu.IgnoreColumns(_table.Columns.Values.Where(a => a.Attribute.CanUpdate == false).Select(a => a.Attribute.Name).ToArray()); - if (_table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true).Any() == false) - ocdu.DoNothing(); - var sql = ocdu.ToSql(); - _params = insert._params; - return sql; + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getInsertSql(ds.Item1, false); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2, true); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getInsertSql(List data, bool flagInsert) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + + string sql = ""; + if (IdentityColumn != null && flagInsert) sql = insert.ToSql(); + else + { + var ocdu = new OnConflictDoUpdate(insert.InsertIdentity()); + ocdu.IgnoreColumns(_table.Columns.Values.Where(a => a.Attribute.CanUpdate == false).Select(a => a.Attribute.Name).ToArray()); + if (_table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true).Any() == false) + ocdu.DoNothing(); + sql = ocdu.ToSql(); + } + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs index 5e4870d7..f8162605 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerInsertOrUpdate.cs @@ -1,5 +1,7 @@ using FreeSql.Internal; using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; @@ -16,28 +18,59 @@ namespace FreeSql.SqlServer.Curd public override string ToSql() { if (_source?.Any() != true) return null; - if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能要求实体类 {_table.CsName} 必须有主键"); - var sb = new StringBuilder().Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getMergeSql(ds.Item1); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getMergeSql(List data) + { + if (_table.Primarys.Any() == false) throw new Exception($"InsertOrUpdate 功能执行 merge into 要求实体类 {_table.CsName} 必须有主键"); + + var sb = new StringBuilder(); + if (IdentityColumn != null) sb.Append("SET IDENTITY_INSERT ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" ON;\r\n"); + sb.Append("MERGE INTO ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" t1 \r\n") .Append("USING ("); - WriteSourceSelectUnionAll(sb); - sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); + WriteSourceSelectUnionAll(data, sb, dbParams); + sb.Append(" ) t2 ON (").Append(string.Join(" AND ", _table.Primarys.Select(a => $"t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}"))).Append(") \r\n"); - var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); - if (cols.Any()) - sb.Append("WHEN MATCHED THEN \r\n") - .Append(" update set ").Append(string.Join(", ", cols.Select(a => - a.Attribute.IsVersion ? - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : - $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" - ))).Append(" \r\n"); + var cols = _table.Columns.Values.Where(a => a.Attribute.IsPrimary == false && a.Attribute.CanUpdate == true); + if (cols.Any()) + sb.Append("WHEN MATCHED THEN \r\n") + .Append(" update set ").Append(string.Join(", ", cols.Select(a => + a.Attribute.IsVersion ? + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t1.{_commonUtils.QuoteSqlName(a.Attribute.Name)} + 1" : + $"{_commonUtils.QuoteSqlName(a.Attribute.Name)} = t2.{a.Attribute.Name}" + ))).Append(" \r\n"); - cols = _table.Columns.Values; - sb.Append("WHEN NOT MATCHED THEN \r\n") - .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") - .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(");"); + cols = _table.Columns.Values; + sb.Append("WHEN NOT MATCHED THEN \r\n") + .Append(" insert (").Append(string.Join(", ", cols.Select(a => _commonUtils.QuoteSqlName(a.Attribute.Name)))).Append(") \r\n") + .Append(" values (").Append(string.Join(", ", cols.Select(a => $"t2.{a.Attribute.Name}"))).Append(");"); - return sb.ToString(); + if (IdentityColumn != null) sb.Append(";\r\nSET IDENTITY_INSERT ").Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append(" OFF;"); + + return sb.ToString(); + } + string getInsertSql(List data) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + return sql; + } } } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs index 4c6838cb..ba2d2189 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteInsertOrUpdate.cs @@ -1,4 +1,7 @@ using FreeSql.Internal; +using System; +using System.Collections.Generic; +using System.Data.Common; using System.Linq; namespace FreeSql.Sqlite.Curd @@ -15,16 +18,35 @@ namespace FreeSql.Sqlite.Curd { if (_source?.Any() != true) return null; - var insert = _orm.Insert() - .AsTable(_tableRule).AsType(_table.Type) - .WithConnection(_connection) - .WithTransaction(_transaction) - .NoneParameter(true) as Internal.CommonProvider.InsertProvider; - insert._source = _source; - var sql = insert.ToSql(); - if (sql.StartsWith("INSERT INTO ") == false) return null; - _params = insert._params; - return $"REPLACE INTO {sql.Substring("INSERT INTO ".Length)}"; + var sqls = new string[2]; + var dbParams = new List(); + var ds = SplitSourceByIdentityValueIsNull(_source); + if (ds.Item1.Any()) sqls[0] = getInsertSql(ds.Item1, false); + if (ds.Item2.Any()) sqls[1] = getInsertSql(ds.Item2, true); + _params = dbParams.ToArray(); + if (ds.Item2.Any() == false) return sqls[0]; + if (ds.Item1.Any() == false) return sqls[1]; + return string.Join("\r\n\r\n;\r\n\r\n", sqls); + + string getInsertSql(List data, bool flagInsert) + { + var insert = _orm.Insert() + .AsTable(_tableRule).AsType(_table.Type) + .WithConnection(_connection) + .WithTransaction(_transaction) + .NoneParameter(true) as Internal.CommonProvider.InsertProvider; + insert._source = data; + + if (IdentityColumn != null && flagInsert == false) insert.InsertIdentity(); + + var sql = insert.ToSql(); + if (string.IsNullOrEmpty(sql)) return null; + if (insert._params?.Any() == true) dbParams.AddRange(insert._params); + if (IdentityColumn != null && flagInsert) return sql; + + if (sql.StartsWith("INSERT INTO ") == false) return null; + return $"REPLACE INTO {sql.Substring("INSERT INTO ".Length)}"; + } } } } \ No newline at end of file