dotnetcore / FreeSql

🦄 .NET aot orm, C# orm, VB.NET orm, Mysql orm, Postgresql orm, SqlServer orm, Oracle orm, Sqlite orm, Firebird orm, 达梦 orm, 人大金仓 orm, 神通 orm, 翰高 orm, 南大通用 orm, 虚谷 orm, 国产 orm, Clickhouse orm, QuestDB orm, MsAccess orm.
http://freesql.net
MIT License
3.99k stars 842 forks source link

mysql分表批量更新故障 #1754

Open MoDao1990217 opened 2 months ago

MoDao1990217 commented 2 months ago

问题描述及重现代码:

mysql InsertOrUpdate批量ExecuteMySqlBulkCopy时,如果表中没相关数据,则插入成功,如表中有相关数据,不会执行更新,而是直接报错误:3 rows were copied to Test_24032017 but only 0 were inserted.

此问题与:#1739 有相关性。https://github.com/dotnetcore/FreeSql/issues/1739

1379 是在分表时,如果不为分表时间字段添加默认值,就会出现问题。

而当前故障是给分表时间字段添加了默认值后,当数据库有值存在时,不会更新,而是直接报错。

调试出错位置在 M6LCJ${1$4NG@G2 U@DV4U 4Z31VZ6L9WT6T0DWJYAWQ1F

下面提供复现demo

IFreeSql fsql = new FreeSql.FreeSqlBuilder()
    .UseConnectionString(FreeSql.DataType.MySql, @"Data Source=127.0.0.1;Port=3306;User ID=root;Password=123456; Initial Catalog=adminDb;Charset=utf8;Allow User Variables=True; SslMode=none;Min pool size=100;AllowLoadLocalInfile=true;")
    .UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}"))//监听SQL语句
    .UseAutoSyncStructure(true) 
    .Build();

var list = new List<Test>()
{
 new Test
 {
      AppId="App1",
       Age=10,
        CreateAt=DateTime.Now,
        Name="1",
 }, new Test
 {
      AppId="App2",
       Age=20,
        CreateAt=DateTime.Now,
        Name="2",
 }, new Test
 {
      AppId="App3",
       Age=30,
        CreateAt=DateTime.Now,
        Name="3",
 }
};

var num = 0;
try
{

    num=fsql.InsertOrUpdate<Test>()
        .SetSource(list)
        .ExecuteMySqlBulkCopy();
    Console.WriteLine($"执行第一次,添加数据:【{num}】条");

    num = fsql.InsertOrUpdate<Test>()
    .SetSource(list)
    .ExecuteMySqlBulkCopy();
    Console.WriteLine($"执行第二次,测试更新数据:【{num}】条");

    Console.WriteLine("执行成功");
}
catch (Exception e)
{
    Console.WriteLine($"出错了:{e.Message}");    
}

Console.ReadLine();

[Table(Name = "Test_{yyMMddHH}", AsTable = $"CreateAt=2024-3-1(1 hour)")]
public class Test
{
    [Column(IsPrimary =true)]
    public string AppId { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    [Column(Name = "CreateAt", CanUpdate = false)]
    public DateTime CreateAt { get; set; }=DateTime.Now;
}

数据库版本

mysql 5.7

安装的Nuget包

Freesql 3.2.815 mysqlconnector 3.2.815

.net framework/. net core? 及具体版本

net 8 控制台程序 net 8 miniapi

2881099 commented 2 months ago

是的,两个是一个问题,当前版本 BulkCopy 未处理自动分表逻辑。

解决办法,指定分表名执行:

fsql.InsertOrUpdate().AsTable("table1").SetSource(list).Execute...

MoDao1990217 commented 2 months ago

是的,两个是一个问题,当前版本 BulkCopy 未处理自动分表逻辑。

解决办法,指定分表名执行:

fsql.InsertOrUpdate().AsTable("table1").SetSource(list).Execute...

指定也不行的,这是这个控制台写的demo版,我没有指定。生产代码,是指定了表名的,还是一样的错误。