【问题标题】:How to deserialize array using Dapper如何使用 Dapper 反序列化数组
【发布时间】:2020-11-05 00:06:03
【问题描述】:

我有一个具有HashSet<int> 成员的模型。由于我无法让 Dapper 自动从数组创建集合,我想我会使用多重映射查询并将数组作为单独的列,拆分并在 lambda 中创建集合。为了清楚起见,我想反序列化整个模型,而不仅仅是集合的位。

我的第一次多重映射尝试也失败了,所以我决定尝试一些更简单的方法,获取一个数组并将其反序列化为List<int>int[]。这就是我卡住的地方。

我使用的是 PostgreSQL 12 数据库。

代码sn-p如下

var query = "SELECT ARRAY[1, 2, 3];";

var ints1 = await _conn.QueryAsync<List<int>>(query); // This returns an empty array
var ints2 = await _conn.QueryAsync<int[]>(query); // System.ArgumentException: Invalid type owner for DynamicMethod.

我不太确定自己做错了什么,Google 似乎也没有帮助,我只发现有关在查询中使用列表的问题。

编辑:好的,我通过将数组转换为 JSON 来实现它,但我仍然觉得这个解决方案很难看。有没有办法避免创建 JSON?

【问题讨论】:

  • 我对 SQL 有点生疏,但 SELECT ARRAY[1, 2, 3] 似乎不是常见的 SQL,postgres 还是没有?我可能会建议 Dapper 可能只是不支持这种非常时髦的语法
  • 我不熟悉postgres,query 是否返回一列3 行?一排三列?还是一行一列?
  • @Crowcoder 它返回一个值为{1, 2, 3}的单行
  • 作为字符串?那么你会如何期望 Dapper 神奇地知道这是一个整数列表?
  • @Liam 以下查询SELECT pg_typeof(ARRAY[1,2,3]) 返回“integer[]”,所以我期待 Dapper 以某种方式知道这不是字符串。此外,以字符串形式获取结果会引发异常。

标签: c# postgresql .net-core dapper


【解决方案1】:

答案在 cmets 中,但 TL;DR 无法做到这一点。数组必须转换为字符串,然后反序列化到列表中。

我正在回答这个问题而不是关闭它,因为如果您主要使用 Postgres 并且可能期望数组在其他 RDMS 中出现,我相信这是一个有效的问题。

【讨论】:

    【解决方案2】:

    不要相信你所听到的一切,虽然上面说不可能,但实际上很容易实现。

    确实,下面的查询会给你报错:(Invalid type owner for DynamicMethod):

    var arrayOfThreeElements =  
            (await _conn.QueryAsync<int[]>("SELECT ARRAY[1, 2, 3]"))                  
                  .FirstOrDefault();
    

    你需要做的是告诉 dapper 如何使用一个小的 TypeHandler 来处理这个问题:

    public class GenericArrayHandler<T> : SqlMapper.TypeHandler<T[]>
    {
        public override void SetValue(IDbDataParameter parameter, T[] value)
        {
            parameter.Value = value;
        }
    
        public override T[] Parse(object value) => (T[]) value;
    }
    

    Parse 方法在这里很重要。

    然后,您只需在添加了所有其他类型处理程序的地方添加此处理程序 - 即在您的应用或网站的初始化代码中,如下所示:

    SqlMapper.AddTypeHandler(new GenericArrayHandler<int>());
    

    现在查询工作并返回整数数组中的 3 个元素,1,2 和 3。

    【讨论】:

    • 您也可以使用通用类型处理程序来执行此操作。 IE。 GenericArrayHandler : SqlMapper.TypeHandler - 并添加新的 GenericArrayHandler()。那么对于遇到的任何数组类型都可以轻松实现目标。
    • 我用提到的 GenericArrayHandler 对其进行了测试,它确实一样好。这使得使用任何类型的数组列变得非常容易。
    • 我将答案改为使用 GenericArrayHandler 来容纳除 int 以外的其他类型
    猜你喜欢
    • 2016-12-03
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 2012-06-30
    • 1970-01-01
    相关资源
    最近更新 更多