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, DuckDB orm, TDengine orm, QuestDB orm, MsAccess orm.
https://freesql.net
MIT License
4.13k stars 859 forks source link

Firebird 数据库 Insert(List source) 执行后字符串字段值被追加空格 #1923

Open ecocom opened 1 week ago

ecocom commented 1 week ago

问题描述及重现代码:

把某码表数据从 SQLite 倒到 Firebird 里后,发现其 Name 字段值大多被追加了空格,造成业务表记录里的对应字段值与码表里的对应不上了,导出导入过程是从 SQLite Select() 出来,然后在 Firebird 中 Insert<T1>(List<T1> source)。

重现:

static void Main(string[] args)
{
    IFreeSql fsql = new FreeSql.FreeSqlBuilder()
        .UseConnectionString(FreeSql.DataType.Firebird, "database=localhost/3050:EMPLOYEE.FDB;user=SYSDBA;password=123456")
        .UseAutoSyncStructure(true)
        .UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper)
        .UseMonitorCommand(cmd => Console.WriteLine($"-- sql@{DateTime.Now:HH:mm:ss.fff} --\n{cmd.CommandText}\n---------\n"))
        .Build();

    List<MyEntity1> srcList = new List<MyEntity1>
    {
        new MyEntity1() { Id = 1, Name = "ab" },
        new MyEntity1() { Id = 2, Name = "abcdef" },
        new MyEntity1() { Id = 3, Name = "abc" }
    };

    fsql.Delete<MyEntity1>().Where(a => true).ExecuteAffrows();
    fsql.Insert(srcList).ExecuteAffrows();

    var list = fsql.Select<MyEntity1>().ToList(a => new
    {
        Id = a.Id,
        Name = a.Name,
        Len = "char_length(a.Name)"
    });
    foreach (var item in list)
    {
        Console.WriteLine($"Id = {item.Id}, Name = {item.Name}, Length(Name) = {item.Len}");
    }

    Console.ReadLine();
}

[Table(Name = "test_myentity1")]
public class MyEntity1
{
    [Column(IsPrimary = true, Position = 1)]
    public long Id { get; set; }

    [Column(StringLength = 50)]
    public string Name { get; set; }
}

输出: iss

如图 SQL 语句为 SELECT xxx UNION ALL SELECT xxx,结果是字符串被追加了空格,长度为 SELECT 里的字符串最大长度。

连接 Firebird 测试,CAST 一下才能正确插入:

INSERT INTO "TEST_MYENTITY1"("ID", "NAME") SELECT FIRST 1 1, CAST ('ab' AS varchar(50)) FROM rdb$database
UNION ALL
 SELECT FIRST 1 2, CAST ('abcdef' AS varchar(50)) FROM rdb$database
UNION ALL
 SELECT FIRST 1 3, CAST ('abc' AS varchar(50)) FROM rdb$database

应该是 Firebird 问题,UNION 时结果为定长 CHAR(字符串最大长度) 了,看看 Insert<T1>(List<T1> source) 能处理不

数据库版本

Firebird 5.0

安装的Nuget包

FreeSql.Provider.Firebird 3.2.830

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

.net 8

2881099 commented 1 week ago

是否第一条 cast 就可以

ecocom commented 1 week ago

可以

2881099 commented 1 week ago

全部都加了

2881099 commented 1 week ago

正在上传中,等5-10分钟后更新。

ecocom commented 1 week ago

好的👍👍