Closed ZeekoZhu closed 1 year ago
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 。
你研究一下原生怎么写的,这个东西不可能等于 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 转换了
我推测 SqlSugar 将我的自定义类型
PgVector
当作实体类型读取了,可是我已经在 Npgsql 设置过自定义类型了,这时 DataReader 返回的应该就是 PgVector 实例,不需要 SqlSugar 转换了
尝试使用实体类型作为 Select 的值
var item = _db.Queryable<VectorItem>()
.Select(x => new VectorItem { Vector = SqlFunc.AggregateAvg(x.Vector), Id = 0 })
.First();
结果生成的 sql 中缺少了聚合列。。。
单个字段识别不了自定义类型 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
感谢,已经没有问题了
例如 pgvector 提供的 vector 类型,需要通过 pgsql 的 TypeMapping 添加自定义的 handler,但是却无法设置 SugarParameter.CustomDbType 为 null ,从而导致 Npgsql 无法使用自定义类型