【问题标题】:How to prevent returned Json being split?如何防止返回的 Json 被拆分?
【发布时间】:2019-08-14 10:37:38
【问题描述】:

我正在使用 Dapper 从 SQL Server 读取数据。我有一个返回长 Json 结果的 SQL 语句,但问题是这个结果被分成 3 行,每行最多 2033 个字符,然后 Dapper 无法解析返回的结果,因为它是无效的 Json。

如何防止这种分裂或如何让 Dapper 处理它?

这是我的代码:

SqlMapper.ResetTypeHandlers();
SqlMapper.AddTypeHandler(new JsonTypeHandler<List<Product>>());

const string sql = @"SELECT 
                         *,
                         (SELECT * FROM Balance b
                          WHERE p.SKU = b.SKU 
                          FOR JSON PATH) AS [Balances]
                     FROM Product p
                     WHERE SKU IN @SKUs
                     FOR JSON PATH";
var connection = new SqlConnection("myconnection");
return connection.QuerySingleAsync<List<Product>>(sql, new{SKUs = new[] {"foo", "bar"}} });

以及TypeHandler的代码:

public class JsonTypeHandler<T> : SqlMapper.TypeHandler<T>
    {
        public override T Parse(object value)
        {
            return JsonConvert.DeserializeObject<T>(value.ToString());
        }

        public override void SetValue(IDbDataParameter parameter, T value)
        {
            parameter.Value = JsonConvert.SerializeObject(value);
        }
    }

这是我在 DataGrip 中运行此 SQL 的方式 编辑: 这是错误消息:

Newtonsoft.Json.JsonSerializationException : 反序列化对象时意外结束。路径 '[0].Balances[4].WarehouseId',第 1 行,位置 2033。

【问题讨论】:

  • 谢谢@DanielA.White,我已经更新了我的问题。
  • 您确定单行数据是拆分成 3 行还是表格中的三个不同记录有 3 行?
  • @AdnanAhmedAnsari 当我复制每一行的值并尝试用jsoneditoronline.org 解析它然后得到无效的 json 消息,但是当组合所有 3 行的值时,我得到了我需要的结果。就像我上面说的,第 1 行和第 2 行各有 2033 个字符。
  • 行为记录在here。我不知道如何用 dapper 修复。也许你应该在返回之前自己连接这些行。

标签: c# sql-server dapper


【解决方案1】:

我的解决方案是编写另一个包装 Query&lt;string&gt; 方法的扩展方法,如下所示:

public static T QueryJson<T>(this IDbConnection cnn, string sql, object param = null,
        IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null,
        CommandType? commandType = null) where T: class
    {
        var result = cnn.Query<string>(sql, param, transaction, buffered, commandTimeout, commandType).ToList();
        if (!result.Any())
            return default(T);

        // Concats
        var sb = new StringBuilder();
        foreach (var jsonPart in result)
            sb.Append(jsonPart);

        var settings = new JsonSerializerSettings
        {
            // https://github.com/danielwertheim/jsonnet-contractresolvers
            // I use this Contract Resolver to set data to private setter properties
            ContractResolver = new PrivateSetterContractResolver()
        };

        // Using Json.Net to de-serialize objects
        return JsonConvert.DeserializeObject<T>(sb.ToString(), settings);
    }

当查询大数据时,这个解决方案效果很好,并且比多映射方法慢(1000 个对象需要 2.7 秒,而 1.3 秒)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多