自定义分表批量插入貌似有BUG 返回

SqlSugar 处理完成
12 178

我用ISplitTableService实现了GetFieldValue,最后一个参数entityValue在批量插入的时候传递的是null,也就是使用 db.Insertable(list) 的时候是null,但是我通过 db.Storageable(list) 却可以正常插入新数据,也自动分表了,不知道是不是BUG,用db.Insertable插入单条数据也没问题,就是用List的时候entityValue是null

热忱回答12

  • https://www.donet5.com/Home/Doc?typeId=2366

    按模版提供你说的测试用例

    0 回复
  • @fate sta:不好意思,解决了,是Insertable没有判断list的数量,空的List依然调用了GetFieldValue,所以是null的值,而Storageable应该是有判断所以是正常的,不知道这算不算一个小BUG。

    0 回复
  • @fate sta:顺便反馈一个自定义类型的问题,db.StorageableByObject不会使用自定义类型,不知道算不算BUG。


    测试代码:

    这个示例的异常触发需要在PropertyGroup设置

    <InvariantGlobalization>true</InvariantGlobalization>


    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Reflection;
    using SqlSugar;
    using DbType = SqlSugar.DbType;
    
    namespace OrmTest
    {
        class SugarDateOnlyConverter : ISugarDataConverter
        {
            /// <inheritdoc />
            public SugarParameter ParameterConverter<T>(object columnValue, int i)
            {
                if (columnValue is not DateOnly dateOnly)
                {
                    throw new ArgumentException("columnValue is not DateOnly");
                }
    
                var name = "@DateOnly" + i;
                return new(name, dateOnly.ToString("O"));
            }
    
            /// <inheritdoc />
            public T QueryConverter<T>(IDataRecord dataRecord, int i)
            {
                var str = dataRecord.GetValue(i) + "";
                return (T)(object)DateOnly.Parse(str);
            }
        }
    
        class Program
        {
            static async Task Main(string[] args)
            {
                var db = new SqlSugarScope(
                    new ConnectionConfig
                    {
                        ConnectionString = "server=localhost;database=test;user=root;password=123456",
                        DbType = DbType.MySql,
                        IsAutoCloseConnection = true
                    }
                );
    
                // 动态建表
                var typeBilder = db.DynamicBuilder().CreateClass("mylogs_dynamic", new());
                typeBilder.CreateProperty(
                    "date",
                    typeof(DateOnly),
                    new() { IsPrimaryKey = true, SqlParameterDbType = typeof(SugarDateOnlyConverter) }
                );
                typeBilder.CreateProperty("d1", typeof(uint), new());
                typeBilder.CreateProperty("d2", typeof(uint), new());
                var type = typeBilder.BuilderType();
                db.CodeFirst.InitTables(type);
                db.DbMaintenance.TruncateTable(type);
    
                // 保存数据
                var log = new Dictionary<string, object>
                {
                    ["date"] = DateOnly.FromDateTime(DateTime.Now),
                    ["d1"] = 1,
                    ["d2"] = 2
                };
                var value = db.DynamicBuilder().CreateObjectByType(type, log);
                // await db.InsertableByObject(value).ExecuteCommandAsync(); // 正常
                db.StorageableByObject(value).ExecuteCommand(); // 异常
    
                Console.WriteLine("用例跑完");
                Console.ReadKey();
            }
        }
    }


    0 回复
  • Storageable 主键为自定义类型没有处理

    0 回复
  • 这个近期修复

    0 回复
  •  DateOnly

    应该是自带就支持的。。。

    0 回复
  • 知道了高级保存主键是dateonly不支持

    0 回复
  • 功能没没有问题

    你的这行代码错了,str要转成2020-01-01这种模式

    image.png



    0 回复
  • @fate sta:对的,这个当时临时测试的,所以没写得完善,主要是反馈没有进自定义类型的问题,因为没进去嘛,所以也不会触发BUG~

    后面我自己根据项目内的情况完善成这样了:

    public class SugarDateOnlyConverter : ISugarDataConverter
    {
        /// <inheritdoc />
        public SugarParameter ParameterConverter<T>(object columnValue, int i)
        {
            var name = "@DateOnly" + i;
            return columnValue switch
            {
                DateOnly dateOnly => new(name, dateOnly.ToString("O")),
                DateTime dateTime => new(name, DateOnly.FromDateTime(dateTime).ToString("O")),
                string str => new(name, str),
                _ => throw new ArgumentException("Invalid type")
            };
        }
    
        /// <inheritdoc />
        public T QueryConverter<T>(IDataRecord dataRecord, int i)
        {
            var result = dataRecord.GetValue(i);
            if (result is DateTime dateTime)
            {
                return (T)(object)DateOnly.FromDateTime(dateTime);
            }
    
            var str = dataRecord.GetValue(i) + "";
            return (T)(object)DateOnly.Parse(str);
        }
    }


    0 回复
  • @fate sta:那个功能没问题是指 db.StorageableByObject(value).ExecuteCommand(); 正常么

    我遇到的这个BUG一定要将InvariantGlobalization设置为true,你可以通过Console.WriteLine(CultureInfo.CurrentCulture == CultureInfo.InvariantCulture);验证一下是不是使用的InvariantCulture。


    因为我部署后的容器是alpine系统,我不需要多国语言所以没有给容器安装icu,这就导致.net会默认使用InvariantCulture,所以就触发了这个BUG。


    Windows本身就自带icu库了,所以正常情况下是没问题的,我们国内就是使用yyyy-MM-dd这种格式,所以默认的ToString没问题,但是失去icu库就不行了。


    那这么看来正常情况下是会调用自定义类型,只是在InvariantCulture下没有去调用自定义类型。。。


    0 回复
  • SqlSugarCore 5.1.4.173-preview07

    过五分钟后勾一下预览已修复

    0 回复
  • @fate stay night谢谢,确认可以了。

    0 回复