如何使用 Dapper 反序列化数组
How to deserialize array using Dapper
我有一个模型有一个 HashSet<int>
成员。由于我无法让 Dapper 自动从数组创建集合,我想我会使用多映射查询并将数组作为单独的列获取,拆分它并在 lambda 中创建集合。明确一点,我想反序列化整个模型,而不仅仅是集合的位。
我的第一次多映射尝试也失败了,所以我决定尝试更简单的方法,获取一个数组并将其反序列化为List<int>
或int[]
。这就是我被困的地方。
我正在使用 PostgreSQL 12 数据库。
代码片段如下
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 使其工作,但我仍然觉得这个解决方案很丑陋。有没有办法避免创建 JSONs?
答案在评论中,但是 TL;DR 这做不到。数组必须转换为字符串,然后反序列化为列表。
我是在回答这个问题而不是关闭它,因为我相信如果您主要使用 Postgres 并且可能期望数组在其他 RDMS 中也是一个东西,那么这是一个有效的问题。
不要相信你听到的一切,虽然上面说这是不可能的,但实际上很容易实现。
确实,下面的查询会给您一个错误:(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>());
现在查询有效,returns 整数数组中的 3 个元素 1,2 和 3。
我有一个模型有一个 HashSet<int>
成员。由于我无法让 Dapper 自动从数组创建集合,我想我会使用多映射查询并将数组作为单独的列获取,拆分它并在 lambda 中创建集合。明确一点,我想反序列化整个模型,而不仅仅是集合的位。
我的第一次多映射尝试也失败了,所以我决定尝试更简单的方法,获取一个数组并将其反序列化为List<int>
或int[]
。这就是我被困的地方。
我正在使用 PostgreSQL 12 数据库。
代码片段如下
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 使其工作,但我仍然觉得这个解决方案很丑陋。有没有办法避免创建 JSONs?
答案在评论中,但是 TL;DR 这做不到。数组必须转换为字符串,然后反序列化为列表。
我是在回答这个问题而不是关闭它,因为我相信如果您主要使用 Postgres 并且可能期望数组在其他 RDMS 中也是一个东西,那么这是一个有效的问题。
不要相信你听到的一切,虽然上面说这是不可能的,但实际上很容易实现。
确实,下面的查询会给您一个错误:(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>());
现在查询有效,returns 整数数组中的 3 个元素 1,2 和 3。