Coldairarrow / EFCore.Sharding

Database Sharding For EFCore
Apache License 2.0
694 stars 144 forks source link

postgresql驱动JsonElement为jsonb字段类型异常 #8

Closed lable closed 4 years ago

lable commented 4 years ago

报异常 Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while updating the entries. See the inner exception for details. ---- System.InvalidOperationException : Operation is not valid due to the current state of the object. 堆栈跟踪: ShardingRepository.PackAccessData(Func1 access) 行 74 ShardingRepository.WriteTable[T](List1 entities, Func3 accessData) 行 119 ShardingRepository.Insert[T](List1 entities) 行 179 ShardingRepository.Insert[T](T entity) 行 171 JsonbTest.Test() 行 72 ----- Inner Stack Trace ----- JsonElement.WriteTo(Utf8JsonWriter writer) JsonConverterJsonElement.Write(Utf8JsonWriter writer, JsonElement value, JsonSerializerOptions options) JsonPropertyInfoNotNullable`4.OnWrite(WriteStackFrame& current, Utf8JsonWriter writer) JsonPropertyInfo.Write(WriteStack& state, Utf8JsonWriter writer) JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state) JsonSerializer.WriteCore(Utf8JsonWriter writer, Object value, Type type, JsonSerializerOptions options) JsonSerializer.WriteCore(PooledByteBufferWriter output, Object value, Type type, JsonSerializerOptions options) JsonSerializer.WriteCoreString(Object value, Type type, JsonSerializerOptions options) JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options) JsonHandler.ValidateAndGetLength[TAny](TAny value, NpgsqlLengthCache& lengthCache, NpgsqlParameter parameter) JsonHandler.ValidateObjectAndGetLength(Object value, NpgsqlLengthCache& lengthCache, NpgsqlParameter parameter) NpgsqlParameter.ValidateAndGetLength() NpgsqlCommand.ValidateParameters(ConnectorTypeMapper typeMapper) NpgsqlCommand.ExecuteReaderAsync(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken) NpgsqlCommand.ExecuteReader(CommandBehavior behavior) NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior) DbCommand.ExecuteReader() RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) ReaderModificationCommandBatch.Execute(IRelationalConnection connection)

模型定义:

   public class JsonbModel
    {
        /// <summary>
        /// 
        /// </summary>
        [Key]
        [Column("id")]
        public Guid Id { get; set; } = SequentialGuid.SequentialGuidGenerator.Instance.NewGuid();// = Guid.NewGuid();

        /// <summary>
        /// 
        /// </summary>
        [Column("content", TypeName = "jsonb")]
        public JsonElement Content { get; set; }

        /// <summary>
        /// 创建时间。
        /// </summary>
        [Column("created_on")]
        public DateTime CreatedOn { get; set; } = DateTime.Now;
    }

测试代码:

    public void Test()
    {
        DateTime startTime = DateTime.Now.AddMinutes(-5);
        DateTime endTime = DateTime.MaxValue;

        //配置初始化
        ShardingConfig.Init(config =>
        {
            config.AddAbsDb(DatabaseType.PostgreSql)//添加抽象数据库
                .AddPhysicDbGroup()//添加物理数据库组
                .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, conn)//添加物理数据库1
                .SetShardingRule(new JsonbShardingRule())//设置分表规则
                .AutoExpandByDate<JsonbModel>(//设置为按时间自动分表
                    ExpandByDateMode.PerMinute,
                    (startTime, endTime, ShardingConfig.DefaultDbGourpName)
                    );
        });
        var db = DbFactory.GetShardingRepository();
        for (var i= 0;i < 10; i++)
        {
            var content = JsonDocument.Parse("{\"id\": \"test\"}").RootElement;
            db.Insert(new JsonbModel
            {
                Content = content
            });

            var count = db.GetIShardingQueryable<JsonbModel>().Count();
            Console.WriteLine($"当前数据量:{count}");

            Thread.Sleep(50);
        }
    }
Coldairarrow commented 4 years ago

不要用PG的高级类型

lable commented 4 years ago

了解! 事实上,jsonb类型如果用string是没有问题的,后续将持续观察下运行情况:

            var where = $"{{\"Details\":[{{\"id\":\"{model.id}\"}}]}}";
            var qry = DbFactory.GetShardingRepository()
                .GetIShardingQueryable<PosOrder>()
                .Where(a => EF.Functions.JsonContained(where, a.Content));
            var posOrder = qry.FirstOrDefault();