- 增加 IFreeSql.InsertOrUpdate 方法 #316

This commit is contained in:
28810 2020-05-21 01:59:35 +08:00
parent 4b7a49d88a
commit 6a443620e7
57 changed files with 4627 additions and 209 deletions

View File

@ -76,6 +76,11 @@ namespace FreeSql
public IInsert<T1> Insert<T1>(T1[] source) where T1 : class => Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(List<T1> source) where T1 : class => Insert<T1>().AppendData(source);
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => Insert<T1>().AppendData(source);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class
{
var db = _resolveDbContext?.Invoke();
db?.FlushCommand();
return _originalFsql.InsertOrUpdate<T1>().WithTransaction(_resolveUnitOfWork()?.GetOrBeginTransaction());
}
}
}

View File

@ -125,13 +125,6 @@
清空状态数据
</summary>
</member>
<member name="M:FreeSql.DbSet`1.RemoveAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据 lambda 条件删除数据
</summary>
<param name="predicate"></param>
<returns></returns>
</member>
<member name="M:FreeSql.DbSet`1.Add(`0)">
<summary>
添加
@ -486,14 +479,5 @@
<param name="that"></param>
<returns></returns>
</member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members>
</doc>

View File

@ -0,0 +1,167 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.MySqlConnector
{
public class MySqlInsertOrUpdateTest
{
IFreeSql fsql => g.mysql;
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(2, '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(2, '02', '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(5, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(8, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '011', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(2, '02', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3)), (2, '02', 0, now(3)), (3, '03', 0, now(3)), (4, '04', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(6, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '001', 0, now(3)), (2, '002', 0, now(3)), (3, '003', 0, now(3)), (4, '004', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(8, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,323 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.Dameng
{
public class DamengInsertOrUpdateTest
{
IFreeSql fsql => g.dameng;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 2 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '02' as ID2, '011' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 2 as ID1, '02' as ID2, '02' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual
UNION ALL
SELECT 2, '02', '02' FROM dual
UNION ALL
SELECT 3, '03', '03' FROM dual
UNION ALL
SELECT 4, '04', '04' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '001' as NAME FROM dual
UNION ALL
SELECT 2, '02', '002' FROM dual
UNION ALL
SELECT 3, '03', '003' FROM dual
UNION ALL
SELECT 4, '04', '004' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '011' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 2 as ID, '02' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '02', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '03', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '04', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '001' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '002', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '003', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '004', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,167 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.MySql
{
public class MySqlInsertOrUpdateTest
{
IFreeSql fsql => g.mysql;
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(2, '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(2, '02', '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '011', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(2, '02', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3)), (2, '02', 0, now(3)), (3, '03', 0, now(3)), (4, '04', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '001', 0, now(3)), (2, '002', 0, now(3)), (3, '003', 0, now(3)), (4, '004', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,195 @@
using FreeSql.DataAnnotations;
using FreeSql.Odbc.MySql;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.MySql
{
public class OnDuplicateKeyUpdateTest
{
class TestOnDuplicateKeyUpdateInfo
{
[Column(IsIdentity = true)]
public int id { get; set; }
public string title { get; set; }
public DateTime time { get; set; }
}
[Fact]
public void ExecuteAffrows()
{
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 100, 101, 102 }).ExecuteAffrows();
var odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 100, title = "title-100", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(100, 'title-100', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = VALUES(`time`)", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 100, title = "title-100", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 101, title = "title-101", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 102, title = "title-102", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(100, 'title-100', '2000-01-01 00:00:00.000'), (101, 'title-101', '2000-01-01 00:00:00.000'), (102, 'title-102', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = VALUES(`time`)", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void IgnoreColumns()
{
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 200, 201, 202 }).ExecuteAffrows();
var odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") }).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(200, 'title-200')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = '2000-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 201, title = "title-201", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 202, title = "title-202", time = DateTime.Parse("2000-01-01") }
}).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(200, 'title-200'), (201, 'title-201'), (202, 'title-202')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = CASE `id`
WHEN 200 THEN '2000-01-01 00:00:00.000'
WHEN 201 THEN '2000-01-01 00:00:00.000'
WHEN 202 THEN '2000-01-01 00:00:00.000' END", odku2.ToSql());
odku2.ExecuteAffrows();
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 200, 201, 202 }).ExecuteAffrows();
odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") }).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity()).IgnoreColumns(a => a.title);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(200, 'title-200')
ON DUPLICATE KEY UPDATE
`time` = '2000-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 201, title = "title-201", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 202, title = "title-202", time = DateTime.Parse("2000-01-01") }
}).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity()).IgnoreColumns(a => a.title);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(200, 'title-200'), (201, 'title-201'), (202, 'title-202')
ON DUPLICATE KEY UPDATE
`time` = CASE `id`
WHEN 200 THEN '2000-01-01 00:00:00.000'
WHEN 201 THEN '2000-01-01 00:00:00.000'
WHEN 202 THEN '2000-01-01 00:00:00.000' END", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void UpdateColumns()
{
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 300, 301, 302 }).ExecuteAffrows();
var odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") }).InsertColumns(a => a.title).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(300, 'title-300')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = '2000-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 301, title = "title-301", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 302, title = "title-302", time = DateTime.Parse("2000-01-01") }
}).InsertColumns(a => a.title).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(300, 'title-300'), (301, 'title-301'), (302, 'title-302')
ON DUPLICATE KEY UPDATE
`title` = VALUES(`title`),
`time` = CASE `id`
WHEN 300 THEN '2000-01-01 00:00:00.000'
WHEN 301 THEN '2000-01-01 00:00:00.000'
WHEN 302 THEN '2000-01-01 00:00:00.000' END", odku2.ToSql());
odku2.ExecuteAffrows();
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 300, 301, 302 }).ExecuteAffrows();
odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") }).InsertColumns(a => a.title).NoneParameter().InsertIdentity()).UpdateColumns(a => a.time);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(300, 'title-300')
ON DUPLICATE KEY UPDATE
`time` = '2000-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 301, title = "title-301", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 302, title = "title-302", time = DateTime.Parse("2000-01-01") }
}).InsertColumns(a => a.title).NoneParameter().InsertIdentity()).UpdateColumns(a => a.time);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`) VALUES(300, 'title-300'), (301, 'title-301'), (302, 'title-302')
ON DUPLICATE KEY UPDATE
`time` = CASE `id`
WHEN 300 THEN '2000-01-01 00:00:00.000'
WHEN 301 THEN '2000-01-01 00:00:00.000'
WHEN 302 THEN '2000-01-01 00:00:00.000' END", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void Set()
{
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 400, 401, 402 }).ExecuteAffrows();
var odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity()).Set(a => a.time, DateTime.Parse("2020-1-1"));
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 401, title = "title-401", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 402, title = "title-402", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity()).Set(a => a.time, DateTime.Parse("2020-1-1"));
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000'), (401, 'title-401', '2000-01-01 00:00:00.000'), (402, 'title-402', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000'", odku2.ToSql());
odku2.ExecuteAffrows();
var dt2020 = DateTime.Parse("2020-1-1");
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 400, 401, 402 }).ExecuteAffrows();
odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity()).Set(a => a.time == dt2020);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 401, title = "title-401", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 402, title = "title-402", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity()).Set(a => a.time == dt2020);
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000'), (401, 'title-401', '2000-01-01 00:00:00.000'), (402, 'title-402', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000'", odku2.ToSql());
odku2.ExecuteAffrows();
g.mysql.Delete<TestOnDuplicateKeyUpdateInfo>(new[] { 400, 401, 402 }).ExecuteAffrows();
odku1 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity()).Set(a => new { time = dt2020, title = a.title + "123" });
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000', `title` = concat(`title`, '123')", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcMySqlOnDuplicateKeyUpdate<TestOnDuplicateKeyUpdateInfo>(g.mysql.Insert(new[] {
new TestOnDuplicateKeyUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 401, title = "title-401", time = DateTime.Parse("2000-01-01") },
new TestOnDuplicateKeyUpdateInfo { id = 402, title = "title-402", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity()).Set(a => new { time = dt2020, title = a.title + "123" });
Assert.Equal(@"INSERT INTO `TestOnDuplicateKeyUpdateInfo`(`id`, `title`, `time`) VALUES(400, 'title-400', '2000-01-01 00:00:00.000'), (401, 'title-401', '2000-01-01 00:00:00.000'), (402, 'title-402', '2000-01-01 00:00:00.000')
ON DUPLICATE KEY UPDATE
`time` = '2020-01-01 00:00:00.000', `title` = concat(`title`, '123')", odku2.ToSql());
odku2.ExecuteAffrows();
}
}
}

View File

@ -0,0 +1,323 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.Oracle
{
public class OracleInsertOrUpdateTest
{
IFreeSql fsql => g.oracle;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 2 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '02' as ID2, '011' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 2 as ID1, '02' as ID2, '02' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual
UNION ALL
SELECT 2, '02', '02' FROM dual
UNION ALL
SELECT 3, '03', '03' FROM dual
UNION ALL
SELECT 4, '04', '04' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '001' as NAME FROM dual
UNION ALL
SELECT 2, '02', '002' FROM dual
UNION ALL
SELECT 3, '03', '003' FROM dual
UNION ALL
SELECT 4, '04', '004' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '011' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 2 as ID, '02' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '02', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '03', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '04', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '001' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '002', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '003', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '004', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,158 @@
using FreeSql.DataAnnotations;
using FreeSql.Odbc.PostgreSQL;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.PostgreSQL
{
public class OnConflictDoUpdateTest
{
class TestOnConflictDoUpdateInfo
{
[Column(IsIdentity = true)]
public int id { get; set; }
public string title { get; set; }
public DateTime? time { get; set; }
}
[Fact]
public void ExecuteAffrows()
{
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 100, 101, 102 }).ExecuteAffrows();
var odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 100, title = "title-100", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"", ""time"") VALUES(100, 'title-100', '2000-01-01 00:00:00.000000')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = EXCLUDED.""time""", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 100, title = "title-100", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 101, title = "title-101", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 102, title = "title-102", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"", ""time"") VALUES(100, 'title-100', '2000-01-01 00:00:00.000000'), (101, 'title-101', '2000-01-01 00:00:00.000000'), (102, 'title-102', '2000-01-01 00:00:00.000000')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = EXCLUDED.""time""", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void IgnoreColumns()
{
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 200, 201, 202 }).ExecuteAffrows();
var odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") }).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(200, 'title-200')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = '2000-01-01 00:00:00.000000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 201, title = "title-201", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 202, title = "title-202", time = DateTime.Parse("2000-01-01") }
}).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(200, 'title-200'), (201, 'title-201'), (202, 'title-202')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = CASE EXCLUDED.""id""
WHEN 200 THEN '2000-01-01 00:00:00.000000'
WHEN 201 THEN '2000-01-01 00:00:00.000000'
WHEN 202 THEN '2000-01-01 00:00:00.000000' END::timestamp", odku2.ToSql());
odku2.ExecuteAffrows();
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 200, 201, 202 }).ExecuteAffrows();
odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") }).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity()).IgnoreColumns(a => a.title);
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(200, 'title-200')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = '2000-01-01 00:00:00.000000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 200, title = "title-200", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 201, title = "title-201", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 202, title = "title-202", time = DateTime.Parse("2000-01-01") }
}).IgnoreColumns(a => a.time).NoneParameter().InsertIdentity()).IgnoreColumns(a => a.title);
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(200, 'title-200'), (201, 'title-201'), (202, 'title-202')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = CASE EXCLUDED.""id""
WHEN 200 THEN '2000-01-01 00:00:00.000000'
WHEN 201 THEN '2000-01-01 00:00:00.000000'
WHEN 202 THEN '2000-01-01 00:00:00.000000' END::timestamp", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void UpdateColumns()
{
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 300, 301, 302 }).ExecuteAffrows();
var odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") }).InsertColumns(a => a.title).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(300, 'title-300')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = '2000-01-01 00:00:00.000000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 301, title = "title-301", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 302, title = "title-302", time = DateTime.Parse("2000-01-01") }
}).InsertColumns(a => a.title).NoneParameter().InsertIdentity());
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(300, 'title-300'), (301, 'title-301'), (302, 'title-302')
ON CONFLICT(""id"") DO UPDATE SET
""title"" = EXCLUDED.""title"",
""time"" = CASE EXCLUDED.""id""
WHEN 300 THEN '2000-01-01 00:00:00.000000'
WHEN 301 THEN '2000-01-01 00:00:00.000000'
WHEN 302 THEN '2000-01-01 00:00:00.000000' END::timestamp", odku2.ToSql());
odku2.ExecuteAffrows();
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 300, 301, 302 }).ExecuteAffrows();
odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") }).InsertColumns(a => a.title).NoneParameter().InsertIdentity()).UpdateColumns(a => a.time);
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(300, 'title-300')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = '2000-01-01 00:00:00.000000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 300, title = "title-300", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 301, title = "title-301", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 302, title = "title-302", time = DateTime.Parse("2000-01-01") }
}).InsertColumns(a => a.title).NoneParameter().InsertIdentity()).UpdateColumns(a => a.time);
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"") VALUES(300, 'title-300'), (301, 'title-301'), (302, 'title-302')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = CASE EXCLUDED.""id""
WHEN 300 THEN '2000-01-01 00:00:00.000000'
WHEN 301 THEN '2000-01-01 00:00:00.000000'
WHEN 302 THEN '2000-01-01 00:00:00.000000' END::timestamp", odku2.ToSql());
odku2.ExecuteAffrows();
}
[Fact]
public void Set()
{
g.pgsql.Delete<TestOnConflictDoUpdateInfo>(new[] { 400, 401, 402 }).ExecuteAffrows();
var odku1 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new TestOnConflictDoUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") }).NoneParameter().InsertIdentity()).Set(a => a.time, DateTime.Parse("2020-1-1"));
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"", ""time"") VALUES(400, 'title-400', '2000-01-01 00:00:00.000000')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = '2020-01-01 00:00:00.000000'", odku1.ToSql());
Assert.Equal(1, odku1.ExecuteAffrows());
var odku2 = new OdbcPostgreSQLOnConflictDoUpdate<TestOnConflictDoUpdateInfo>(g.pgsql.Insert(new[] {
new TestOnConflictDoUpdateInfo { id = 400, title = "title-400", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 401, title = "title-401", time = DateTime.Parse("2000-01-01") },
new TestOnConflictDoUpdateInfo { id = 402, title = "title-402", time = DateTime.Parse("2000-01-01") }
}).NoneParameter().InsertIdentity()).Set(a => a.time, DateTime.Parse("2020-1-1"));
Assert.Equal(@"INSERT INTO ""testonconflictdoupdateinfo""(""id"", ""title"", ""time"") VALUES(400, 'title-400', '2000-01-01 00:00:00.000000'), (401, 'title-401', '2000-01-01 00:00:00.000000'), (402, 'title-402', '2000-01-01 00:00:00.000000')
ON CONFLICT(""id"") DO UPDATE SET
""time"" = '2020-01-01 00:00:00.000000'", odku2.ToSql());
odku2.ExecuteAffrows();
}
}
}

View File

@ -0,0 +1,205 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.PostgreSQL
{
public class PostgreSQLInsertOrUpdateTest
{
IFreeSql fsql => g.pgsql;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(0, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(2)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(0, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(1, '01')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(1, '011')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(2, '02')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '02', '011')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(2, '02', '02')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '01', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '011', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(2, '02', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '01', 0, current_timestamp), (2, '02', 0, current_timestamp), (3, '03', 0, current_timestamp), (4, '04', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '001', 0, current_timestamp), (2, '002', 0, current_timestamp), (3, '003', 0, current_timestamp), (4, '004', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,323 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Odbc.SqlServer
{
public class SqlServerInsertOrUpdateTest
{
IFreeSql fsql => g.sqlserver;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(0, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 2 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4 ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4 ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(0, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'01' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'02' as id2, N'011' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 2 as id1, N'02' as id2, N'02' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'01' as name
UNION ALL
SELECT 2, N'02', N'02'
UNION ALL
SELECT 3, N'03', N'03'
UNION ALL
SELECT 4, N'04', N'04' ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'001' as name
UNION ALL
SELECT 2, N'02', N'002'
UNION ALL
SELECT 3, N'03', N'003'
UNION ALL
SELECT 4, N'04', N'004' ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'01' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'011' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 2 as id, N'02' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'01' as name, 0 as version, getdate() as CreateTime
UNION ALL
SELECT 2, N'02', 0, getdate()
UNION ALL
SELECT 3, N'03', 0, getdate()
UNION ALL
SELECT 4, N'04', 0, getdate() ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'001' as name, 0 as version, getdate() as CreateTime
UNION ALL
SELECT 2, N'002', 0, getdate()
UNION ALL
SELECT 3, N'003', 0, getdate()
UNION ALL
SELECT 4, N'004', 0, getdate() ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,323 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Dameng
{
public class DamengInsertOrUpdateTest
{
IFreeSql fsql => g.dameng;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 2 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
iou.ExecuteAffrows();
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '02' as ID2, '011' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 2 as ID1, '02' as ID2, '02' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual
UNION ALL
SELECT 2, '02', '02' FROM dual
UNION ALL
SELECT 3, '03', '03' FROM dual
UNION ALL
SELECT 4, '04', '04' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '001' as NAME FROM dual
UNION ALL
SELECT 2, '02', '002' FROM dual
UNION ALL
SELECT 3, '03', '003' FROM dual
UNION ALL
SELECT 4, '04', '004' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '011' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 2 as ID, '02' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '02', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '03', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '04', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '001' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '002', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '003', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '004', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
iou.ExecuteAffrows();
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,167 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.MySql
{
public class MySqlInsertOrUpdateTest
{
IFreeSql fsql => g.mysql;
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(1, '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`id`, `name`) VALUES(2, '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou02`(`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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '011')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(2, '02', '02')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(5, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou03`(`id1`, `id2`, `name`) VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`)", sql);
Assert.Equal(8, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '011', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(2, '02', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '01', 0, now(3)), (2, '02', 0, now(3)), (3, '03', 0, now(3)), (4, '04', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(6, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO `tbiou04`(`id`, `name`, `version`, `CreateTime`) VALUES(1, '001', 0, now(3)), (2, '002', 0, now(3)), (3, '003', 0, now(3)), (4, '004', 0, now(3))
ON DUPLICATE KEY UPDATE
`name` = VALUES(`name`),
`version` = `version` + 1", sql);
Assert.Equal(8, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,323 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Oracle
{
public class OracleInsertOrUpdateTest
{
IFreeSql fsql => g.oracle;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
Assert.Equal(0, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 2 as ID FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU01"" t1
USING (SELECT 1 as ID FROM dual
UNION ALL
SELECT 2 FROM dual
UNION ALL
SELECT 3 FROM dual
UNION ALL
SELECT 4 FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN NOT MATCHED THEN
insert (""ID"")
values (t2.ID)", sql);
Assert.Equal(0, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU02"" 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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '02' as ID2, '011' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 2 as ID1, '02' as ID2, '02' as NAME FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '01' as NAME FROM dual
UNION ALL
SELECT 2, '02', '02' FROM dual
UNION ALL
SELECT 3, '03', '03' FROM dual
UNION ALL
SELECT 4, '04', '04' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU03"" t1
USING (SELECT 1 as ID1, '01' as ID2, '001' as NAME FROM dual
UNION ALL
SELECT 2, '02', '002' FROM dual
UNION ALL
SELECT 3, '03', '003' FROM dual
UNION ALL
SELECT 4, '04', '004' FROM dual ) t2 ON (t1.""ID1"" = t2.ID1 AND t1.""ID2"" = t2.ID2)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME
WHEN NOT MATCHED THEN
insert (""ID1"", ""ID2"", ""NAME"")
values (t2.ID1, t2.ID2, t2.NAME)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '011' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 2 as ID, '02' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '01' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '02', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '03', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '04', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO ""TBIOU04"" t1
USING (SELECT 1 as ID, '001' as NAME, 0 as VERSION, systimestamp as CREATETIME FROM dual
UNION ALL
SELECT 2, '002', 0, systimestamp FROM dual
UNION ALL
SELECT 3, '003', 0, systimestamp FROM dual
UNION ALL
SELECT 4, '004', 0, systimestamp FROM dual ) t2 ON (t1.""ID"" = t2.ID)
WHEN MATCHED THEN
update set ""NAME"" = t2.NAME, ""VERSION"" = t1.""VERSION"" + 1
WHEN NOT MATCHED THEN
insert (""ID"", ""NAME"", ""VERSION"", ""CREATETIME"")
values (t2.ID, t2.NAME, t2.VERSION, t2.CREATETIME)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,205 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.PostgreSQL
{
public class PostgreSQLInsertOrUpdateTest
{
IFreeSql fsql => g.pgsql;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(0, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(2)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)
ON CONFLICT(""id"") DO NOTHING", sql);
Assert.Equal(0, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(1, '01')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(1, '011')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""id"", ""name"") VALUES(2, '02')
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""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<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou02""(""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<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '02', '011')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(2, '02', '02')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')
ON CONFLICT(""id1"", ""id2"") DO UPDATE SET
""name"" = EXCLUDED.""name""", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '01', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '011', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(2, '02', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '01', 0, current_timestamp), (2, '02', 0, current_timestamp), (3, '03', 0, current_timestamp), (4, '04', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"INSERT INTO ""tbiou04""(""id"", ""name"", ""version"", ""createtime"") VALUES(1, '001', 0, current_timestamp), (2, '002', 0, current_timestamp), (3, '003', 0, current_timestamp), (4, '004', 0, current_timestamp)
ON CONFLICT(""id"") DO UPDATE SET
""name"" = EXCLUDED.""name"",
""version"" = ""tbiou04"".""version"" + 1", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,325 @@
using FreeSql.DataAnnotations;
using FreeSql.Tests.DataContext.SqlServer;
using SaleIDO.Entity.Storeage;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.SqlServer
{
public class SqlServerInsertOrUpdateTest
{
IFreeSql fsql => g.sqlserver;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(0, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 2 as id ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4 ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(2, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou01] t1
USING (SELECT 1 as id
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4 ) t2 ON (t1.[id] = t2.id)
WHEN NOT MATCHED THEN
insert ([id])
values (t2.id);", sql);
Assert.Equal(0, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou02] 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);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'01' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'02' as id2, N'011' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 2 as id1, N'02' as id2, N'02' as name ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'01' as name
UNION ALL
SELECT 2, N'02', N'02'
UNION ALL
SELECT 3, N'03', N'03'
UNION ALL
SELECT 4, N'04', N'04' ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou03] t1
USING (SELECT 1 as id1, N'01' as id2, N'001' as name
UNION ALL
SELECT 2, N'02', N'002'
UNION ALL
SELECT 3, N'03', N'003'
UNION ALL
SELECT 4, N'04', N'004' ) t2 ON (t1.[id1] = t2.id1 AND t1.[id2] = t2.id2)
WHEN MATCHED THEN
update set [name] = t2.name
WHEN NOT MATCHED THEN
insert ([id1], [id2], [name])
values (t2.id1, t2.id2, t2.name);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'01' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'011' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 2 as id, N'02' as name, 0 as version, getdate() as CreateTime ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'01' as name, 0 as version, getdate() as CreateTime
UNION ALL
SELECT 2, N'02', 0, getdate()
UNION ALL
SELECT 3, N'03', 0, getdate()
UNION ALL
SELECT 4, N'04', 0, getdate() ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"MERGE INTO [tbiou04] t1
USING (SELECT 1 as id, N'001' as name, 0 as version, getdate() as CreateTime
UNION ALL
SELECT 2, N'002', 0, getdate()
UNION ALL
SELECT 3, N'003', 0, getdate()
UNION ALL
SELECT 4, N'004', 0, getdate() ) t2 ON (t1.[id] = t2.id)
WHEN MATCHED THEN
update set [name] = t2.name, [version] = t1.[version] + 1
WHEN NOT MATCHED THEN
insert ([id], [name], [version], [CreateTime])
values (t2.id, t2.name, t2.version, t2.CreateTime);", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -0,0 +1,165 @@
using FreeSql.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace FreeSql.Tests.Sqlite
{
public class SqliteInsertOrUpdateTest
{
IFreeSql fsql => g.sqlite;
[Fact]
public void InsertOrUpdate_OnlyPrimary()
{
fsql.Delete<tbiou01>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
var sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou01""(""id"") VALUES(1)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 1 });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou01""(""id"") VALUES(1)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new tbiou01 { id = 2 });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou01""(""id"") VALUES(2)", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou01>().SetSource(new[] { new tbiou01 { id = 1 }, new tbiou01 { id = 2 }, new tbiou01 { id = 3 }, new tbiou01 { id = 4 } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou01""(""id"") VALUES(1), (2), (3), (4)", sql);
Assert.Equal(4, iou.ExecuteAffrows());
}
class tbiou01
{
public int id { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimary()
{
fsql.Delete<tbiou02>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou02""(""id"", ""name"") VALUES(1, '01')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou02""(""id"", ""name"") VALUES(1, '011')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new tbiou02 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou02""(""id"", ""name"") VALUES(2, '02')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "01" }, new tbiou02 { id = 2, name = "02" }, new tbiou02 { id = 3, name = "03" }, new tbiou02 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou02""(""id"", ""name"") VALUES(1, '01'), (2, '02'), (3, '03'), (4, '04')", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou02>().SetSource(new[] { new tbiou02 { id = 1, name = "001" }, new tbiou02 { id = 2, name = "002" }, new tbiou02 { id = 3, name = "003" }, new tbiou02 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou02""(""id"", ""name"") VALUES(1, '001'), (2, '002'), (3, '003'), (4, '004')", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou02>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou02
{
public int id { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_TwoPrimary()
{
fsql.Delete<tbiou03>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "01", name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 1, id2 = "02", name = "011" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '02', '011')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new tbiou03 { id1 = 2, id2 = "02", name = "02" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(2, '02', '02')", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "01" }, new tbiou03 { id1 = 2, id2 = "02", name = "02" }, new tbiou03 { id1 = 3, id2 = "03", name = "03" }, new tbiou03 { id1 = 4, id2 = "04", name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '01'), (2, '02', '02'), (3, '03', '03'), (4, '04', '04')", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou03>().SetSource(new[] { new tbiou03 { id1 = 1, id2 = "01", name = "001" }, new tbiou03 { id1 = 2, id2 = "02", name = "002" }, new tbiou03 { id1 = 3, id2 = "03", name = "003" }, new tbiou03 { id1 = 4, id2 = "04", name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou03""(""id1"", ""id2"", ""name"") VALUES(1, '01', '001'), (2, '02', '002'), (3, '03', '003'), (4, '04', '004')", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou03>().Where(a => a.id1 == 1 && a.id2 == "01" || a.id1 == 2 && a.id2 == "02" || a.id1 == 3 && a.id2 == "03" || a.id1 == 4 && a.id2 == "04").ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id1).Count());
}
class tbiou03
{
[Column(IsPrimary = true)]
public int id1 { get; set; }
[Column(IsPrimary = true)]
public string id2 { get; set; }
public string name { get; set; }
}
[Fact]
public void InsertOrUpdate_OnePrimaryAndVersionAndCanUpdate()
{
fsql.Delete<tbiou04>().Where("1=1").ExecuteAffrows();
var iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "01" });
var sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou04""(""id"", ""name"", ""version"", ""CreateTime"") VALUES(1, '01', 0, datetime(current_timestamp,'localtime'))", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 1, name = "011" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou04""(""id"", ""name"", ""version"", ""CreateTime"") VALUES(1, '011', 0, datetime(current_timestamp,'localtime'))", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new tbiou04 { id = 2, name = "02" });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou04""(""id"", ""name"", ""version"", ""CreateTime"") VALUES(2, '02', 0, datetime(current_timestamp,'localtime'))", sql);
Assert.Equal(1, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "01" }, new tbiou04 { id = 2, name = "02" }, new tbiou04 { id = 3, name = "03" }, new tbiou04 { id = 4, name = "04" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou04""(""id"", ""name"", ""version"", ""CreateTime"") VALUES(1, '01', 0, datetime(current_timestamp,'localtime')), (2, '02', 0, datetime(current_timestamp,'localtime')), (3, '03', 0, datetime(current_timestamp,'localtime')), (4, '04', 0, datetime(current_timestamp,'localtime'))", sql);
Assert.Equal(4, iou.ExecuteAffrows());
iou = fsql.InsertOrUpdate<tbiou04>().SetSource(new[] { new tbiou04 { id = 1, name = "001" }, new tbiou04 { id = 2, name = "002" }, new tbiou04 { id = 3, name = "003" }, new tbiou04 { id = 4, name = "004" } });
sql = iou.ToSql();
Assert.Equal(@"REPLACE INTO ""tbiou04""(""id"", ""name"", ""version"", ""CreateTime"") VALUES(1, '001', 0, datetime(current_timestamp,'localtime')), (2, '002', 0, datetime(current_timestamp,'localtime')), (3, '003', 0, datetime(current_timestamp,'localtime')), (4, '004', 0, datetime(current_timestamp,'localtime'))", sql);
Assert.Equal(4, iou.ExecuteAffrows());
var lst = fsql.Select<tbiou04>().Where(a => new[] { 1, 2, 3, 4 }.Contains(a.id)).ToList();
Assert.Equal(4, lst.Where(a => a.name == "00" + a.id).Count());
}
class tbiou04
{
public int id { get; set; }
public string name { get; set; }
[Column(IsVersion = true)]
public int version { get; set; }
[Column(CanUpdate = false, ServerTime = DateTimeKind.Local)]
public DateTime CreateTime { get; set; }
}
}
}

View File

@ -1011,6 +1011,60 @@
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.WithTransaction(System.Data.Common.DbTransaction)">
<summary>
指定事务对象
</summary>
<param name="transaction"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.WithConnection(System.Data.Common.DbConnection)">
<summary>
指定事务对象
</summary>
<param name="connection"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.SetSource(`0)">
<summary>
添加或更新,设置实体
</summary>
<param name="source">实体</param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.SetSource(System.Collections.Generic.IEnumerable{`0})">
<summary>
添加或更新,设置实体集合
</summary>
<param name="source">实体集合</param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.AsTable(System.Func{System.String,System.String})">
<summary>
设置表名规则,可用于分库/分表参数1默认表名返回值新表名
</summary>
<param name="tableRule"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.AsType(System.Type)">
<summary>
动态Type在使用 Update&lt;object&gt; 后使用本方法,指定实体类型
</summary>
<param name="entityType"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.ToSql">
<summary>
返回即将执行的SQL语句
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.IInsertOrUpdate`1.ExecuteAffrows">
<summary>
执行SQL语句返回影响的行数
</summary>
<returns></returns>
</member>
<member name="F:FreeSql.FieldAliasOptions.AsIndex">
<summary>
自动产生 as1, as2, as3 .... 字段别名<para></para>
@ -2337,137 +2391,6 @@
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询若使用读写分离查询【从库】条件cmdText.StartsWith("SELECT "),否则查询【主库】
</summary>
<param name="readerHander"></param>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteReaderAsync(System.Func{System.Data.Common.DbDataReader,System.Threading.Tasks.Task},System.String,System.Object)">
<summary>
查询ExecuteReaderAsync(dr => {}, "select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteArrayAsync(System.String,System.Object)">
<summary>
查询ExecuteArrayAsync("select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataSetAsync(System.String,System.Object)">
<summary>
查询ExecuteDataSetAsync("select * from user where age > ?age; select 2", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
查询
</summary>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteDataTableAsync(System.String,System.Object)">
<summary>
查询ExecuteDataTableAsync("select * from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteNonQueryAsync(System.String,System.Object)">
<summary>
在【主库】执行ExecuteNonQueryAsync("delete from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
在【主库】执行
</summary>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
</member>
<member name="M:FreeSql.IAdo.ExecuteScalarAsync(System.String,System.Object)">
<summary>
在【主库】执行ExecuteScalarAsync("select 1 from user where age > ?age", new { age = 25 })
</summary>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > ?age", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``1(System.String,System.Object)">
<summary>
执行SQL返回对象集合QueryAsync&lt;User&gt;("select * from user where age > ?age", new { age = 25 })
</summary>
<typeparam name="T"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.Data.CommandType,System.String,System.Data.Common.DbParameter[])">
<summary>
执行SQL返回对象集合Query&lt;User&gt;("select * from user where age > ?age; select * from address", new SqlParameter { ParameterName = "age", Value = 25 })
</summary>
<typeparam name="T1"></typeparam>
<param name="cmdType"></param>
<param name="cmdText"></param>
<param name="cmdParms"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IAdo.QueryAsync``2(System.String,System.Object)">
<summary>
执行SQL返回对象集合Query&lt;User&gt;("select * from user where age > ?age; select * from address", new { age = 25 })
</summary>
<typeparam name="T1"></typeparam>
<param name="cmdText"></param>
<param name="parms"></param>
<returns></returns>
</member>
<member name="E:FreeSql.IAop.ParseExpression">
<summary>
可自定义解析表达式
@ -3063,12 +2986,6 @@
<param name="timeout">超时</param>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.GetAsync">
<summary>
获取资源
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IObjectPool`1.Return(FreeSql.Internal.ObjectPool.Object{`0},System.Boolean)">
<summary>
使用完毕后,归还资源
@ -3139,12 +3056,6 @@
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnGetAsync(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
</summary>
<param name="obj">资源对象</param>
</member>
<member name="M:FreeSql.Internal.ObjectPool.IPolicy`1.OnReturn(FreeSql.Internal.ObjectPool.Object{`0})">
<summary>
归还对象给对象池的时候触发
@ -3685,6 +3596,19 @@
<param name="source"></param>
<returns></returns>
</member>
<member name="M:IFreeSql.InsertOrUpdate``1">
<summary>
插入或更新数据<para></para>
MySql: on duplicate key update<para></para>
PostgreSQL: on conflict do update<para></para>
SqlServer: merge into<para></para>
Oracle: merge into<para></para>
Sqlite: replace into<para></para>
Dameng: merge into<para></para>
</summary>
<typeparam name="T1"></typeparam>
<returns></returns>
</member>
<member name="M:IFreeSql.Update``1">
<summary>
修改数据

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace FreeSql
{
public interface IInsertOrUpdate<T1> where T1 : class
{
/// <summary>
/// 指定事务对象
/// </summary>
/// <param name="transaction"></param>
/// <returns></returns>
IInsertOrUpdate<T1> WithTransaction(DbTransaction transaction);
/// <summary>
/// 指定事务对象
/// </summary>
/// <param name="connection"></param>
/// <returns></returns>
IInsertOrUpdate<T1> WithConnection(DbConnection connection);
/// <summary>
/// 添加或更新,设置实体
/// </summary>
/// <param name="source">实体</param>
/// <returns></returns>
IInsertOrUpdate<T1> SetSource(T1 source);
/// <summary>
/// 添加或更新,设置实体集合
/// </summary>
/// <param name="source">实体集合</param>
/// <returns></returns>
IInsertOrUpdate<T1> SetSource(IEnumerable<T1> source);
/// <summary>
/// 设置表名规则,可用于分库/分表参数1默认表名返回值新表名
/// </summary>
/// <param name="tableRule"></param>
/// <returns></returns>
IInsertOrUpdate<T1> AsTable(Func<string, string> tableRule);
/// <summary>
/// 动态Type在使用 Update&lt;object&gt; 后使用本方法,指定实体类型
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
IInsertOrUpdate<T1> AsType(Type entityType);
/// <summary>
/// 返回即将执行的SQL语句
/// </summary>
/// <returns></returns>
string ToSql();
/// <summary>
/// 执行SQL语句返回影响的行数
/// </summary>
/// <returns></returns>
int ExecuteAffrows();
#if net40
#else
Task<int> ExecuteAffrowsAsync();
#endif
}
}

View File

@ -201,7 +201,7 @@ namespace FreeSql.Aop
/// </summary>
public DbParameter[] DbParms { get; }
}
public enum CurdType { Select, Delete, Update, Insert }
public enum CurdType { Select, Delete, Update, Insert, InsertOrUpdate }
public class CurdAfterEventArgs : CurdBeforeEventArgs
{
public CurdAfterEventArgs(CurdBeforeEventArgs before, Exception exception, object executeResult) :
@ -324,7 +324,7 @@ namespace FreeSql.Aop
private object _value;
public bool IsChanged { get; private set; }
}
public enum AuditValueType { Update, Insert }
public enum AuditValueType { Update, Insert, InsertOrUpdate }
#endregion
#region CommandBefore/After

View File

@ -44,6 +44,19 @@ public interface IFreeSql : IDisposable
/// <returns></returns>
IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class;
/// <summary>
/// 插入或更新数据<para></para>
/// MySql: on duplicate key update<para></para>
/// PostgreSQL: on conflict do update<para></para>
/// SqlServer: merge into<para></para>
/// Oracle: merge into<para></para>
/// Sqlite: replace into<para></para>
/// Dameng: merge into<para></para>
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <returns></returns>
IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class;
/// <summary>
/// 修改数据
/// </summary>

View File

@ -0,0 +1,222 @@
using FreeSql.Extensions.EntityUtil;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Internal.CommonProvider
{
public abstract partial class InsertOrUpdateProvider<T1> : IInsertOrUpdate<T1> where T1 : class
{
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected Func<string, string> _tableRule;
protected DbParameter[] _params;
protected DbTransaction _transaction;
protected DbConnection _connection;
public InsertOrUpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
{
_orm = orm;
_commonUtils = commonUtils;
_commonExpression = commonExpression;
_table = _commonUtils.GetTableByEntity(typeof(T1));
if (_orm.CodeFirst.IsAutoSyncStructure && typeof(T1) != typeof(object)) _orm.CodeFirst.SyncStructure<T1>();
}
protected void ClearData()
{
_source.Clear();
_auditValueChangedDict.Clear();
}
public IInsertOrUpdate<T1> WithTransaction(DbTransaction transaction)
{
_transaction = transaction;
_connection = _transaction?.Connection;
return this;
}
public IInsertOrUpdate<T1> WithConnection(DbConnection connection)
{
if (_transaction?.Connection != connection) _transaction = null;
_connection = connection;
return this;
}
public static void AuditDataValue(object sender, IEnumerable<T1> data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{
if (data?.Any() != true) return;
if (orm.Aop.AuditValueHandler == null) return;
foreach (var d in data)
{
if (d == null) continue;
foreach (var col in table.Columns.Values)
{
object val = col.GetMapValue(d);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties[col.CsName], val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.IsChanged)
{
col.SetMapValue(d, val = auditArgs.Value);
if (changedDict != null && changedDict.ContainsKey(col.Attribute.Name) == false)
changedDict.Add(col.Attribute.Name, true);
}
}
}
}
public static void AuditDataValue(object sender, T1 data, IFreeSql orm, TableInfo table, Dictionary<string, bool> changedDict)
{
if (orm.Aop.AuditValueHandler == null) return;
if (data == null) return;
if (typeof(T1) == typeof(object) && new[] { table.Type, table.TypeLazy }.Contains(data.GetType()) == false)
throw new Exception($"操作的数据类型({data.GetType().DisplayCsharp()}) 与 AsType({table.Type.DisplayCsharp()}) 不一致,请检查。");
foreach (var col in table.Columns.Values)
{
object val = col.GetMapValue(data);
var auditArgs = new Aop.AuditValueEventArgs(Aop.AuditValueType.InsertOrUpdate, col, table.Properties[col.CsName], val);
orm.Aop.AuditValueHandler(sender, auditArgs);
if (auditArgs.IsChanged)
{
col.SetMapValue(data, val = auditArgs.Value);
if (changedDict != null && changedDict.ContainsKey(col.Attribute.Name) == false)
changedDict.Add(col.Attribute.Name, true);
}
}
}
public IInsertOrUpdate<T1> SetSource(T1 source) => this.SetSource(new[] { source });
public IInsertOrUpdate<T1> SetSource(IEnumerable<T1> source)
{
if (source == null || source.Any() == false) return this;
AuditDataValue(this, source, _orm, _table, _auditValueChangedDict);
_source.AddRange(source.Where(a => a != null));
return this;
}
protected string TableRuleInvoke()
{
if (_tableRule == null) return _table.DbName;
var newname = _tableRule(_table.DbName);
if (newname == _table.DbName) return _table.DbName;
if (string.IsNullOrEmpty(newname)) return _table.DbName;
if (_orm.CodeFirst.IsSyncStructureToLower) newname = newname.ToLower();
if (_orm.CodeFirst.IsSyncStructureToUpper) newname = newname.ToUpper();
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_table.Type, newname);
return newname;
}
public IInsertOrUpdate<T1> AsTable(Func<string, string> tableRule)
{
_tableRule = tableRule;
return this;
}
public IInsertOrUpdate<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IInsertOrUpdate.AsType 参数不支持指定为 object");
if (entityType == _table.Type) return this;
var newtb = _commonUtils.GetTableByEntity(entityType);
_table = newtb ?? throw new Exception("IInsertOrUpdate.AsType 参数错误,请传入正确的实体类型");
if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(entityType);
return this;
}
public void WriteSourceSelectUnionAll(StringBuilder sb)
{
var specialParams = new List<DbParameter>();
var didx = 0;
foreach (var d in _source)
{
if (didx > 0) sb.Append(" \r\nUNION ALL\r\n ");
sb.Append("SELECT ");
var colidx2 = 0;
foreach (var col in _table.Columns.Values)
{
if (colidx2 > 0) sb.Append(", ");
if (string.IsNullOrEmpty(col.DbInsertValue) == false)
sb.Append(col.DbInsertValue);
else
{
object val = col.GetMapValue(d);
sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val));
}
if (didx == 0) sb.Append(" as ").Append(col.Attribute.Name);
++colidx2;
}
switch (_orm.Ado.DataType)
{
case DataType.OdbcOracle:
case DataType.Oracle:
case DataType.OdbcDameng:
case DataType.Dameng:
sb.Append(" FROM dual");
break;
}
++didx;
}
if (specialParams.Any()) _params = specialParams.ToArray();
}
public abstract string ToSql();
public int ExecuteAffrows()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.InsertOrUpdate, sql, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var affrows = 0;
Exception exception = null;
try
{
affrows = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _params);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
}
return affrows;
}
#if net40
#else
async public Task<int> ExecuteAffrowsAsync()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.InsertOrUpdate, sql, _params);
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
var affrows = 0;
Exception exception = null;
try
{
affrows = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _params);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new Aop.CurdAfterEventArgs(before, exception, affrows);
_orm.Aop.CurdAfterHandler?.Invoke(this, after);
}
return affrows;
}
#endif
}
}

View File

@ -15,20 +15,20 @@ namespace FreeSql.Internal.CommonProvider
public abstract partial class InsertProvider<T1> : IInsert<T1> where T1 : class
{
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected Func<string, string> _tableRule;
protected bool _noneParameter, _insertIdentity;
protected int _batchValuesLimit, _batchParameterLimit;
protected bool _batchAutoTransaction = true;
protected DbParameter[] _params;
protected DbTransaction _transaction;
protected DbConnection _connection;
public IFreeSql _orm;
public CommonUtils _commonUtils;
public CommonExpression _commonExpression;
public List<T1> _source = new List<T1>();
public Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
public Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
public TableInfo _table;
public Func<string, string> _tableRule;
public bool _noneParameter, _insertIdentity;
public int _batchValuesLimit, _batchParameterLimit;
public bool _batchAutoTransaction = true;
public DbParameter[] _params;
public DbTransaction _transaction;
public DbConnection _connection;
public InsertProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
{
@ -509,7 +509,7 @@ namespace FreeSql.Internal.CommonProvider
++colidx;
}
sb.Append(") ");
if (isValues) sb.Append(isValues ? "VALUES" : "SELECT ");
if (isValues) sb.Append("VALUES");
_params = _noneParameter ? new DbParameter[0] : new DbParameter[colidx * _source.Count];
var specialParams = new List<DbParameter>();
var didx = 0;

View File

@ -15,25 +15,25 @@ namespace FreeSql.Internal.CommonProvider
public abstract partial class UpdateProvider<T1> : IUpdate<T1> where T1 : class
{
protected IFreeSql _orm;
protected CommonUtils _commonUtils;
protected CommonExpression _commonExpression;
protected List<T1> _source = new List<T1>();
protected Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
protected TableInfo _table;
protected Func<string, string> _tableRule;
protected StringBuilder _where = new StringBuilder();
protected List<GlobalFilter.Item> _whereGlobalFilter;
protected StringBuilder _set = new StringBuilder();
protected StringBuilder _setIncr = new StringBuilder();
protected List<DbParameter> _params = new List<DbParameter>();
protected List<DbParameter> _paramsSource = new List<DbParameter>();
protected bool _noneParameter;
protected int _batchRowsLimit, _batchParameterLimit;
protected bool _batchAutoTransaction = true;
protected DbTransaction _transaction;
protected DbConnection _connection;
public IFreeSql _orm;
public CommonUtils _commonUtils;
public CommonExpression _commonExpression;
public List<T1> _source = new List<T1>();
public Dictionary<string, bool> _ignore = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
public Dictionary<string, bool> _auditValueChangedDict = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
public TableInfo _table;
public Func<string, string> _tableRule;
public StringBuilder _where = new StringBuilder();
public List<GlobalFilter.Item> _whereGlobalFilter;
public StringBuilder _set = new StringBuilder();
public StringBuilder _setIncr = new StringBuilder();
public List<DbParameter> _params = new List<DbParameter>();
public List<DbParameter> _paramsSource = new List<DbParameter>();
public bool _noneParameter;
public int _batchRowsLimit, _batchParameterLimit;
public bool _batchAutoTransaction = true;
public DbTransaction _transaction;
public DbConnection _connection;
public UpdateProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
{

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.Dameng.Curd
{
class DamengInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public DamengInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -24,6 +24,7 @@ namespace FreeSql.Dameng
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new DamengUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new DamengDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new DamengDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new DamengInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -24,6 +24,7 @@ namespace FreeSql.MsAccess
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new MsAccessUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new MsAccessDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new MsAccessDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => throw new NotImplementedException();
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -0,0 +1,29 @@
using FreeSql.Internal;
using System.Linq;
namespace FreeSql.MySql.Curd
{
class MySqlInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public MySqlInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
public override string ToSql()
{
if (_source?.Any() != true) return null;
var insert = _orm.Insert<T1>()
.AsTable(_tableRule).AsType(_table.Type)
.WithConnection(_connection)
.WithTransaction(_transaction)
.NoneParameter(true) as Internal.CommonProvider.InsertProvider<T1>;
insert._source = _source;
var sql = new OnDuplicateKeyUpdate<T1>(insert).ToSql();
_params = insert._params;
return sql;
}
}
}

View File

@ -1,11 +1,6 @@
using FreeSql.Aop;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

View File

@ -50,6 +50,7 @@ namespace FreeSql.MySql
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new MySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new MySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new MySqlInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.Odbc.Dameng
{
class OdbcDamengInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OdbcDamengInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.Odbc.Dameng
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcDamengUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcDamengDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcDamengDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OdbcDamengInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -26,6 +26,7 @@ namespace FreeSql.Odbc.Default
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => throw new NotImplementedException();
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -1,4 +1,5 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using FreeSql.Internal.ObjectPool;
using System;
using System.Collections.Generic;
@ -17,11 +18,30 @@ namespace FreeSql.Odbc.MySql
{
}
internal bool InternalIsIgnoreInto = false;
internal IFreeSql InternalOrm => _orm;
internal TableInfo InternalTable => _table;
internal DbParameter[] InternalParams => _params;
internal DbConnection InternalConnection => _connection;
internal DbTransaction InternalTransaction => _transaction;
internal CommonUtils InternalCommonUtils => _commonUtils;
internal CommonExpression InternalCommonExpression => _commonExpression;
internal List<T1> InternalSource => _source;
internal Dictionary<string, bool> InternalIgnore => _ignore;
internal void InternalClearData() => ClearData();
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override string ToSql()
{
if (InternalIsIgnoreInto == false) return base.ToSqlValuesOrSelectUnionAll();
var sql = base.ToSqlValuesOrSelectUnionAll();
return $"INSERT IGNORE INTO {sql.Substring(12)}";
}
protected override long RawExecuteIdentity()
{
var sql = this.ToSql();

View File

@ -0,0 +1,29 @@
using FreeSql.Internal;
using System.Linq;
namespace FreeSql.Odbc.MySql
{
class OdbcMySqlInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OdbcMySqlInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
public override string ToSql()
{
if (_source?.Any() != true) return null;
var insert = _orm.Insert<T1>()
.AsTable(_tableRule).AsType(_table.Type)
.WithConnection(_connection)
.WithTransaction(_transaction)
.NoneParameter(true) as Internal.CommonProvider.InsertProvider<T1>;
insert._source = _source;
var sql = new OdbcMySqlOnDuplicateKeyUpdate<T1>(insert).ToSql();
_params = insert._params;
return sql;
}
}
}

View File

@ -0,0 +1,166 @@
using FreeSql.Aop;
using System;
using System.Data;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Odbc.MySql
{
public class OdbcMySqlOnDuplicateKeyUpdate<T1> where T1 : class
{
internal OdbcMySqlInsert<T1> _mysqlInsert;
internal OdbcMySqlUpdate<T1> _mysqlUpdatePriv;
internal OdbcMySqlUpdate<T1> _mysqlUpdate => _mysqlUpdatePriv ?? (_mysqlUpdatePriv = new OdbcMySqlUpdate<T1>(_mysqlInsert.InternalOrm, _mysqlInsert.InternalCommonUtils, _mysqlInsert.InternalCommonExpression, null).NoneParameter().SetSource(_mysqlInsert.InternalSource) as OdbcMySqlUpdate<T1>);
public OdbcMySqlOnDuplicateKeyUpdate(IInsert<T1> insert)
{
_mysqlInsert = insert as OdbcMySqlInsert<T1>;
if (_mysqlInsert == null) throw new Exception("OnDuplicateKeyUpdate 是 FreeSql.Provider.Odbc/MySql 特有的功能");
}
protected void ClearData()
{
_mysqlInsert.InternalClearData();
_mysqlUpdatePriv = null;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns)
{
_mysqlUpdate.IgnoreColumns(columns);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> UpdateColumns(Expression<Func<T1, object>> columns)
{
_mysqlUpdate.UpdateColumns(columns);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> IgnoreColumns(string[] columns)
{
_mysqlUpdate.IgnoreColumns(columns);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> UpdateColumns(string[] columns)
{
_mysqlUpdate.UpdateColumns(columns);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value)
{
_mysqlUpdate.Set(column, value);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> exp)
{
_mysqlUpdate.Set(exp);
return this;
}
public OdbcMySqlOnDuplicateKeyUpdate<T1> SetRaw(string sql)
{
_mysqlUpdate.SetRaw(sql);
return this;
}
public string ToSql()
{
var sb = new StringBuilder();
sb.Append(_mysqlInsert.ToSql()).Append("\r\nON DUPLICATE KEY UPDATE\r\n");
var sbSetEmpty = _mysqlUpdate.InternalSbSet.Length == 0;
var sbSetIncrEmpty = _mysqlUpdate.InternalSbSetIncr.Length == 0;
if (sbSetEmpty == false || sbSetIncrEmpty == false)
{
if (sbSetEmpty == false) sb.Append(_mysqlUpdate.InternalSbSet.ToString().Substring(2));
if (sbSetIncrEmpty == false) sb.Append(sbSetEmpty ? _mysqlUpdate.InternalSbSetIncr.ToString().Substring(2) : _mysqlUpdate.InternalSbSetIncr.ToString());
}
else
{
var colidx = 0;
foreach (var col in _mysqlInsert.InternalTable.Columns.Values)
{
if (col.Attribute.IsPrimary || _mysqlUpdate.InternalIgnore.ContainsKey(col.Attribute.Name)) continue;
if (colidx > 0) sb.Append(", \r\n");
if (col.Attribute.IsVersion == true)
{
var field = _mysqlInsert.InternalCommonUtils.QuoteSqlName(col.Attribute.Name);
sb.Append(field).Append(" = ").Append(field).Append(" + 1");
}
else if (_mysqlInsert.InternalIgnore.ContainsKey(col.Attribute.Name))
{
var caseWhen = _mysqlUpdate.InternalWhereCaseSource(col.CsName, sqlval => sqlval).Trim();
sb.Append(caseWhen);
if (caseWhen.EndsWith(" END")) _mysqlUpdate.InternalToSqlCaseWhenEnd(sb, col);
}
else
{
var field = _mysqlInsert.InternalCommonUtils.QuoteSqlName(col.Attribute.Name);
sb.Append(field).Append(" = VALUES(").Append(field).Append(")");
}
++colidx;
}
}
return sb.ToString();
}
public long ExecuteAffrows()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new CurdBeforeEventArgs(_mysqlInsert.InternalTable.Type, _mysqlInsert.InternalTable, CurdType.Insert, sql, _mysqlInsert.InternalParams);
_mysqlInsert.InternalOrm.Aop.CurdBeforeHandler?.Invoke(_mysqlInsert, before);
long ret = 0;
Exception exception = null;
try
{
ret = _mysqlInsert.InternalOrm.Ado.ExecuteNonQuery(_mysqlInsert.InternalConnection, _mysqlInsert.InternalTransaction, CommandType.Text, sql, _mysqlInsert.InternalParams);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new CurdAfterEventArgs(before, exception, ret);
_mysqlInsert.InternalOrm.Aop.CurdAfterHandler?.Invoke(_mysqlInsert, after);
ClearData();
}
return ret;
}
#if net40
#else
async public Task<long> ExecuteAffrowsAsync()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new CurdBeforeEventArgs(_mysqlInsert.InternalTable.Type, _mysqlInsert.InternalTable, CurdType.Insert, sql, _mysqlInsert.InternalParams);
_mysqlInsert.InternalOrm.Aop.CurdBeforeHandler?.Invoke(_mysqlInsert, before);
long ret = 0;
Exception exception = null;
try
{
ret = await _mysqlInsert.InternalOrm.Ado.ExecuteNonQueryAsync(_mysqlInsert.InternalConnection, _mysqlInsert.InternalTransaction, CommandType.Text, sql, _mysqlInsert.InternalParams);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new CurdAfterEventArgs(before, exception, ret);
_mysqlInsert.InternalOrm.Aop.CurdAfterHandler?.Invoke(_mysqlInsert, after);
ClearData();
}
return ret;
}
#endif
}
}

View File

@ -18,10 +18,16 @@ namespace FreeSql.Odbc.MySql
{
}
internal StringBuilder InternalSbSet => _set;
internal StringBuilder InternalSbSetIncr => _setIncr;
internal Dictionary<string, bool> InternalIgnore => _ignore;
internal void InternalResetSource(List<T1> source) => _source = source;
internal string InternalWhereCaseSource(string CsName, Func<string, string> thenValue) => WhereCaseSource(CsName, thenValue);
internal void InternalToSqlCaseWhenEnd(StringBuilder sb, ColumnInfo col) => ToSqlCaseWhenEnd(sb, col);
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
protected override List<T1> RawExecuteUpdated()
{
var sql = this.ToSql();

View File

@ -28,6 +28,7 @@ namespace FreeSql.Odbc.MySql
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcMySqlUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcMySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcMySqlDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OdbcMySqlInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.Odbc.Oracle
{
class OdbcOracleInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OdbcOracleInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.Odbc.Oracle
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcOracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcOracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcOracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OdbcOracleInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -1,7 +1,9 @@
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -16,6 +18,17 @@ namespace FreeSql.Odbc.PostgreSQL
{
}
internal IFreeSql InternalOrm => _orm;
internal TableInfo InternalTable => _table;
internal DbParameter[] InternalParams => _params;
internal DbConnection InternalConnection => _connection;
internal DbTransaction InternalTransaction => _transaction;
internal CommonUtils InternalCommonUtils => _commonUtils;
internal CommonExpression InternalCommonExpression => _commonExpression;
internal List<T1> InternalSource => _source;
internal Dictionary<string, bool> InternalIgnore => _ignore;
internal void InternalClearData() => ClearData();
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override long ExecuteIdentity() => base.SplitExecuteIdentity(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override List<T1> ExecuteInserted() => base.SplitExecuteInserted(_batchValuesLimit > 0 ? _batchValuesLimit : 5000, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);

View File

@ -0,0 +1,33 @@
using FreeSql.Internal;
using System.Linq;
namespace FreeSql.Odbc.PostgreSQL
{
class OdbcPostgreSQLInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OdbcPostgreSQLInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
public override string ToSql()
{
if (_source?.Any() != true) return null;
var insert = _orm.Insert<T1>()
.AsTable(_tableRule).AsType(_table.Type)
.WithConnection(_connection)
.WithTransaction(_transaction)
.NoneParameter(true) as Internal.CommonProvider.InsertProvider<T1>;
insert._source = _source;
var ocdu = new OdbcPostgreSQLOnConflictDoUpdate<T1>(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;
}
}
}

View File

@ -0,0 +1,207 @@
using FreeSql.Aop;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace FreeSql.Odbc.PostgreSQL
{
public class OdbcPostgreSQLOnConflictDoUpdate<T1> where T1 : class
{
internal OdbcPostgreSQLInsert<T1> _pgsqlInsert;
internal OdbcPostgreSQLUpdate<T1> _pgsqlUpdatePriv;
internal OdbcPostgreSQLUpdate<T1> _pgsqlUpdate => _pgsqlUpdatePriv ??
(_pgsqlUpdatePriv = new OdbcPostgreSQLUpdate<T1>(_pgsqlInsert.InternalOrm, _pgsqlInsert.InternalCommonUtils, _pgsqlInsert.InternalCommonExpression, null) { InternalTableAlias = "EXCLUDED" }
.NoneParameter().SetSource(_pgsqlInsert.InternalSource) as OdbcPostgreSQLUpdate<T1>);
ColumnInfo[] _columns;
bool _doNothing;
public OdbcPostgreSQLOnConflictDoUpdate(IInsert<T1> insert, Expression<Func<T1, object>> columns = null)
{
_pgsqlInsert = insert as OdbcPostgreSQLInsert<T1>;
if (_pgsqlInsert == null) throw new Exception("OnConflictDoUpdate 是 FreeSql.Provider.Odbc/PostgreSQL 特有的功能");
if (columns != null)
{
var colsList = new List<ColumnInfo>();
var cols = _pgsqlInsert.InternalCommonExpression.ExpressionSelectColumns_MemberAccess_New_NewArrayInit(null, columns?.Body, false, null).ToDictionary(a => a, a => true);
foreach (var col in _pgsqlInsert.InternalTable.Columns.Values)
if (cols.ContainsKey(col.Attribute.Name))
colsList.Add(col);
_columns = colsList.ToArray();
}
if (_columns == null || _columns.Any() == false)
_columns = _pgsqlInsert.InternalTable.Primarys;
if (_columns.Any() == false) throw new Exception("OnConflictDoUpdate 功能要求实体类必须设置 IsPrimary 属性");
}
protected void ClearData()
{
_pgsqlInsert.InternalClearData();
_pgsqlUpdatePriv = null;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns)
{
_pgsqlUpdate.IgnoreColumns(columns);
return this;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> UpdateColumns(Expression<Func<T1, object>> columns)
{
_pgsqlUpdate.UpdateColumns(columns);
return this;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> IgnoreColumns(string[] columns)
{
_pgsqlUpdate.IgnoreColumns(columns);
return this;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> UpdateColumns(string[] columns)
{
_pgsqlUpdate.UpdateColumns(columns);
return this;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value)
{
_pgsqlUpdate.Set(column, value);
return this;
}
//由于表达式解析问题ON CONFLICT("id") DO UPDATE SET 需要指定表别名,如 Set(a => a.Clicks + 1) 解析会失败
//暂时不开放这个功能,如有需要使用 SetRaw("click = t.click + 1") 替代该操作
//public OnConflictDoUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> exp)
//{
// _pgsqlUpdate.Set(exp);
// return this;
//}
public OdbcPostgreSQLOnConflictDoUpdate<T1> SetRaw(string sql)
{
_pgsqlUpdate.SetRaw(sql);
return this;
}
public OdbcPostgreSQLOnConflictDoUpdate<T1> DoNothing()
{
_doNothing = true;
return this;
}
public string ToSql()
{
var sb = new StringBuilder();
sb.Append(_pgsqlInsert.ToSql()).Append("\r\nON CONFLICT(");
for (var a = 0; a < _columns.Length; a++)
{
if (a > 0) sb.Append(", ");
sb.Append(_pgsqlInsert.InternalCommonUtils.QuoteSqlName(_columns[a].Attribute.Name));
}
if (_doNothing)
{
sb.Append(") DO NOTHING");
}
else
{
sb.Append(") DO UPDATE SET\r\n");
var sbSetEmpty = _pgsqlUpdate.InternalSbSet.Length == 0;
var sbSetIncrEmpty = _pgsqlUpdate.InternalSbSetIncr.Length == 0;
if (sbSetEmpty == false || sbSetIncrEmpty == false)
{
if (sbSetEmpty == false) sb.Append(_pgsqlUpdate.InternalSbSet.ToString().Substring(2));
if (sbSetIncrEmpty == false) sb.Append(sbSetEmpty ? _pgsqlUpdate.InternalSbSetIncr.ToString().Substring(2) : _pgsqlUpdate.InternalSbSetIncr.ToString());
}
else
{
var colidx = 0;
foreach (var col in _pgsqlInsert.InternalTable.Columns.Values)
{
if (col.Attribute.IsPrimary || _pgsqlUpdate.InternalIgnore.ContainsKey(col.Attribute.Name)) continue;
if (colidx > 0) sb.Append(", \r\n");
if (col.Attribute.IsVersion == true)
{
var field = _pgsqlInsert.InternalCommonUtils.QuoteSqlName(col.Attribute.Name);
sb.Append(field).Append(" = ").Append(_pgsqlInsert.InternalCommonUtils.QuoteSqlName(_pgsqlInsert.InternalTable.DbName)).Append(".").Append(field).Append(" + 1");
}
else if (_pgsqlInsert.InternalIgnore.ContainsKey(col.Attribute.Name))
{
var caseWhen = _pgsqlUpdate.InternalWhereCaseSource(col.CsName, sqlval => sqlval).Trim();
sb.Append(caseWhen);
if (caseWhen.EndsWith(" END")) _pgsqlUpdate.InternalToSqlCaseWhenEnd(sb, col);
}
else
{
var field = _pgsqlInsert.InternalCommonUtils.QuoteSqlName(col.Attribute.Name);
sb.Append(field).Append(" = EXCLUDED.").Append(field);
}
++colidx;
}
}
}
return sb.ToString();
}
public long ExecuteAffrows()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new CurdBeforeEventArgs(_pgsqlInsert.InternalTable.Type, _pgsqlInsert.InternalTable, CurdType.Insert, sql, _pgsqlInsert.InternalParams);
_pgsqlInsert.InternalOrm.Aop.CurdBeforeHandler?.Invoke(_pgsqlInsert, before);
long ret = 0;
Exception exception = null;
try
{
ret = _pgsqlInsert.InternalOrm.Ado.ExecuteNonQuery(_pgsqlInsert.InternalConnection, _pgsqlInsert.InternalTransaction, CommandType.Text, sql, _pgsqlInsert.InternalParams);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new CurdAfterEventArgs(before, exception, ret);
_pgsqlInsert.InternalOrm.Aop.CurdAfterHandler?.Invoke(_pgsqlInsert, after);
ClearData();
}
return ret;
}
#if net40
#else
async public Task<long> ExecuteAffrowsAsync()
{
var sql = this.ToSql();
if (string.IsNullOrEmpty(sql)) return 0;
var before = new CurdBeforeEventArgs(_pgsqlInsert.InternalTable.Type, _pgsqlInsert.InternalTable, CurdType.Insert, sql, _pgsqlInsert.InternalParams);
_pgsqlInsert.InternalOrm.Aop.CurdBeforeHandler?.Invoke(_pgsqlInsert, before);
long ret = 0;
Exception exception = null;
try
{
ret = await _pgsqlInsert.InternalOrm.Ado.ExecuteNonQueryAsync(_pgsqlInsert.InternalConnection, _pgsqlInsert.InternalTransaction, CommandType.Text, sql, _pgsqlInsert.InternalParams);
}
catch (Exception ex)
{
exception = ex;
throw ex;
}
finally
{
var after = new CurdAfterEventArgs(before, exception, ret);
_pgsqlInsert.InternalOrm.Aop.CurdAfterHandler?.Invoke(_pgsqlInsert, after);
ClearData();
}
return ret;
}
#endif
}
}

View File

@ -18,6 +18,14 @@ namespace FreeSql.Odbc.PostgreSQL
{
}
internal string InternalTableAlias;
internal StringBuilder InternalSbSet => _set;
internal StringBuilder InternalSbSetIncr => _setIncr;
internal Dictionary<string, bool> InternalIgnore => _ignore;
internal void InternalResetSource(List<T1> source) => _source = source;
internal string InternalWhereCaseSource(string CsName, Func<string, string> thenValue) => WhereCaseSource(CsName, thenValue);
internal void InternalToSqlCaseWhenEnd(StringBuilder sb, ColumnInfo col) => ToSqlCaseWhenEnd(sb, col);
public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
public override List<T1> ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 3000);
@ -65,6 +73,7 @@ namespace FreeSql.Odbc.PostgreSQL
if (_table.Primarys.Length == 1)
{
var pk = _table.Primarys.First();
if (string.IsNullOrEmpty(InternalTableAlias) == false) caseWhen.Append(InternalTableAlias).Append(".");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
return;
}
@ -73,6 +82,7 @@ namespace FreeSql.Odbc.PostgreSQL
foreach (var pk in _table.Primarys)
{
if (pkidx > 0) caseWhen.Append(" || '+' || ");
if (string.IsNullOrEmpty(InternalTableAlias) == false) caseWhen.Append(InternalTableAlias).Append(".");
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))).Append("::varchar");
++pkidx;
}

View File

@ -27,6 +27,7 @@ namespace FreeSql.Odbc.PostgreSQL
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcPostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcPostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcPostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OdbcPostgreSQLInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -1,9 +1,7 @@
using FreeSql.Internal;
using FreeSql.Internal.ObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Threading.Tasks;

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.Odbc.SqlServer
{
class OdbcSqlServerInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OdbcSqlServerInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -23,6 +23,7 @@ namespace FreeSql.Odbc.SqlServer
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OdbcSqlServerUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OdbcSqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OdbcSqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OdbcSqlServerInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.Oracle.Curd
{
class OracleInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public OracleInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -24,6 +24,7 @@ namespace FreeSql.Oracle
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new OracleInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -1,14 +1,11 @@
using FreeSql.Aop;
using FreeSql.Internal;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FreeSql.PostgreSQL.Curd

View File

@ -0,0 +1,33 @@
using FreeSql.Internal;
using System.Linq;
namespace FreeSql.PostgreSQL.Curd
{
class PostgreSQLInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public PostgreSQLInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
public override string ToSql()
{
if (_source?.Any() != true) return null;
var insert = _orm.Insert<T1>()
.AsTable(_tableRule).AsType(_table.Type)
.WithConnection(_connection)
.WithTransaction(_transaction)
.NoneParameter(true) as Internal.CommonProvider.InsertProvider<T1>;
insert._source = _source;
var ocdu = new OnConflictDoUpdate<T1>(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;
}
}
}

View File

@ -77,6 +77,7 @@ namespace FreeSql.PostgreSQL
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new PostgreSQLUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new PostgreSQLDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new PostgreSQLInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -1,10 +1,8 @@
using FreeSql.Internal;
using FreeSql.Internal.ObjectPool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

View File

@ -0,0 +1,43 @@
using FreeSql.Internal;
using System;
using System.Linq;
using System.Text;
namespace FreeSql.SqlServer.Curd
{
class SqlServerInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public SqlServerInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
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 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();
}
}
}

View File

@ -24,6 +24,7 @@ namespace FreeSql.SqlServer
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new SqlServerUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new SqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new SqlServerDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new SqlServerInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }

View File

@ -0,0 +1,30 @@
using FreeSql.Internal;
using System.Linq;
namespace FreeSql.Sqlite.Curd
{
class SqliteInsertOrUpdate<T1> : Internal.CommonProvider.InsertOrUpdateProvider<T1> where T1 : class
{
public SqliteInsertOrUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
: base(orm, commonUtils, commonExpression)
{
}
public override string ToSql()
{
if (_source?.Any() != true) return null;
var insert = _orm.Insert<T1>()
.AsTable(_tableRule).AsType(_table.Type)
.WithConnection(_connection)
.WithTransaction(_transaction)
.NoneParameter(true) as Internal.CommonProvider.InsertProvider<T1>;
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)}";
}
}
}

View File

@ -24,6 +24,7 @@ namespace FreeSql.Sqlite
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new SqliteUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IDelete<T1> Delete<T1>() where T1 : class => new SqliteDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new SqliteDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
public IInsertOrUpdate<T1> InsertOrUpdate<T1>() where T1 : class => new SqliteInsertOrUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
public IAdo Ado { get; }
public IAop Aop { get; }