PostgresSQL 无法映射自定义数据库类型
ZeekoZhu opened this issue · comments
https://www.donet5.com/Home/Doc?typeId=2542 sqlsugar有自定义类型
https://www.donet5.com/Home/Doc?typeId=2542 sqlsugar有自定义类型
我的使用场景跟这篇文档有些不同, pgvector 是 pgsql 的一个插件,提供了一个新的数据库类型 vector
,我需要将一个 dotnet class 映射到 vector 类型。创建 ISugarDataConverter 是必须的,否则 SqlSugar 无法正确设置参数类型,默认是 String,我需要将其设置为 vector 类型。
除了参数外,在读取数据的时候也需要配置 Npgsql 的 TypeHandler,否则 Npgsql 驱动将无法识别 vector 类型。
但是现在问题出现了,在 ISugarDataConverter.ParameterConverter 中,必须要将 CustomDbType 设置成一个非 Null 的值,否则最终生成的 NpgsqlParamter.NpgsqlDbType 将是 string。但是 Npgsql 的自定义 TypeHandler 只会处理 NpgsqlDbType 字段为 Null 的参数。
我查阅了 SqlSugar 的代码,并没有办法将最终生成的 NpgsqlParamter.NpgsqlDbType 设置成 null 。
找到了一个方法:
var parameter = new SugarParameter(name, null)
{
DbType = DbType.Object, // 调用 NpgsqlParameter.DbType 的 setter 将 NpgsqlDbType 设置成 null
Value = value // 重新设置 Value,避免 SqlSugar 自动将 value 转换成 JSON string
};
能用就行
var other = new PgVector(new[] { 1.0f, 2.0f, 3.0f });
var item = _db.Queryable<VectorItem>().Select(x => VectorOperator.Distance(x.Vector, other)).First();
我发现在查询的时候,Expression 中的参数无法被 SqlSugar 的自定义类型 Converter 处理,导致 SugarParameter 的 DbType 被设置为 AsciiString
类似的情况还有下面这种:
var item = _db.Queryable<VectorItem>()
.Select(x => SqlFunc.AggregateAvg(x.Vector))
.First();
报错:
System.ArgumentNullException : Value cannot be null. (Parameter 'con')
at System.Reflection.Emit.DynamicILGenerator.Emit(OpCode opcode, ConstructorInfo con)
at SqlSugar.IDataReaderEntityBuilder`1.CreateBuilder(Type type)
at SqlSugar.DbBindAccessory.<>c__DisplayClass4_0`1.<GetEntityList>b__0()
at SqlSugar.ReflectionInoCore`1.GetOrCreate(String cacheKey, Func`1 create)
at SqlSugar.ReflectionInoCacheService.GetOrCreate[V](String cacheKey, Func`1 create, Int32 cacheDurationInSeconds)
at SqlSugar.DbBindAccessory.GetEntityList[T](SqlSugarProvider context, IDataReader dataReader)
at SqlSugar.DbBindProvider.DataReaderToList[T](Type type, IDataReader dataReader)
at SqlSugar.QueryableProvider`1.GetData[TResult](Boolean isComplexModel, Type entityType, IDataReader dataReader)
at SqlSugar.QueryableProvider`1.GetData[TResult](KeyValuePair`2 sqlObj)
at SqlSugar.QueryableProvider`1._ToList[TResult]()
at SqlSugar.QueryableProvider`1.ToList()
at SqlSugar.QueryableProvider`1.First()
我推测 SqlSugar 将我的自定义类型 PgVector
当作实体类型读取了,可是我已经在 Npgsql 设置过自定义类型了,这时 DataReader 返回的应该就是 PgVector 实例,不需要 SqlSugar 转换了
单个字段识别不了自定义类型
new class(){ 有特性的属性=SqlFunc.AggregateAvg(x.Vector)}
这样就能识别
我来验证一下
var item = _db.Queryable<VectorItem>()
.Select(x => new VectorItem { Vector = SqlFunc.AggregateAvg(x.Vector), Id = 0 })
.First();
你这个应该把ID去掉,如果2个字段需要GROUP BY
感谢,已经没有问题了