You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Npgsql至3.2.7后,hstore列转XPO类属性遇IConvertible错误

解决Npgsql 3.2.7升级后XPO读取hstore列报"IConvertible"错误的问题

我之前处理过类似的Npgsql版本升级后和XPO适配的问题,你的情况核心原因是Npgsql 3.x对hstore类型的处理逻辑完全变了,咱们一步步来解决:

问题根源

在Npgsql 2.2.5版本中,hstore列会直接以字符串形式返回(比如"key1=>val1,key2=>val2"),所以你的XPO值转换器可以直接基于字符串解析成List<Tuple<object, object>>。但升级到3.2.7后,Npgsql会返回NpgsqlTypes.NpgsqlHstore类型的对象,不再是原始字符串——你的旧转换器还是按字符串来处理,类型不匹配就触发了"an object should implement IConvertible"的错误。

解决方案

1. 修改XPO值转换器适配NpgsqlHstore

你需要把原来处理字符串的逻辑改成处理NpgsqlHstore对象,示例代码如下:

using DevExpress.Xpo.Metadata;
using NpgsqlTypes;
using System;
using System.Collections.Generic;
using System.Linq;

public class HstoreToTupleListConverter : ValueConverter
{
    public override Type StorageType => typeof(NpgsqlHstore);

    public override object ConvertFromStorageType(object value)
    {
        if (value == null || value == DBNull.Value)
            return new List<Tuple<object, object>>();
        
        // 现在value是NpgsqlHstore类型,直接遍历其键值对
        var hstore = (NpgsqlHstore)value;
        return hstore.Select(kvp => Tuple.Create((object)kvp.Key, (object)kvp.Value)).ToList();
    }

    public override object ConvertToStorageType(object value)
    {
        var tupleList = value as List<Tuple<object, object>>;
        if (tupleList == null || !tupleList.Any())
            return DBNull.Value;
        
        // 将Tuple列表转成NpgsqlHstore
        var hstoreDict = tupleList.ToDictionary(t => t.Item1.ToString(), t => t.Item2?.ToString());
        return new NpgsqlHstore(hstoreDict);
    }
}

2. 注册转换器到XPO字典

确保在XPO初始化时,把这个转换器注册到对应的hstore属性上:

// 假设你的XPO类是YourPersistentClass,对应的hstore属性是HstoreData
var dict = new ReflectionDictionary();
dict.GetClassInfo(typeof(YourPersistentClass))
    .GetMember(nameof(YourPersistentClass.HstoreData))
    .SetValueConverter(new HstoreToTupleListConverter());

3. 确认程序集版本一致性

检查你的项目引用:

  • Npgsql版本必须是3.2.7,不能混合旧版本
  • 如果使用了DevExpress的Npgsql XPO集成包(比如DevExpress.Xpo.vXX.Npgsql),也要确保版本和Npgsql兼容(3.2.7对应的集成包版本需要匹配你的DevExpress版本)

额外注意点

  • 测试双向转换:不仅要测试读取hstore列,还要测试修改List<Tuple<object, object>>后写入数据库是否正常
  • 如果你的Tuple类型有特殊值(比如非字符串类型),需要在转换时做额外的类型处理,避免ToString()丢失信息

内容的提问来源于stack exchange,提问作者leszy77

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:08:03