LinqToDB报错:投影类型ES_PRODUCT找不到关联键'Oid'
问题描述
以下代码可正常运行,能从表中查询记录并投影到新对象,正确获取结果:
var results98 = (from record in x.Psi.Psiproductparts from infoRecord in record.Programpressinforecords let p = new ES_WONPROGRAMPRESSINFORMATIONRECORD() { record_title = infoRecord.PpiTitle } select p.record_title).ToArray();
但下方代码执行失败:
var results97 = (from record in x.Psi.Psiproductparts let bar = new ES_PRODUCT { p_product_programpressinformationrecords = from infoRecord in record .Programpressinforecords select new ES_WONPROGRAMPRESSINFORMATIONRECORD() { record_title = infoRecord.PpiTitle } } from infoRecord2 in bar.p_product_programpressinformationrecords select infoRecord2.record_title).ToArray();
报错信息:
LinqToDB.Linq.LinqException HResult=0x80131500 Message=Association key 'Oid' not found for type 'Linq2DbPostgresWon.ES_PRODUCT.
其中ES_PRODUCT仅为普通载体类,并非数据库表,定义如下:
class ES_PRODUCT { public IEnumerable<ES_WONPROGRAMPRESSINFORMATIONRECORD>? p_product_programpressinformationrecords { get; set; } }
问题原因
LinqToDB的查询解析逻辑在处理嵌套查询时,误将带有集合属性的ES_PRODUCT识别为需要数据库关联的实体类。它会尝试为这类类型查找默认的关联键(比如Oid),但ES_PRODUCT只是普通的数据传输对象(DTO),并没有定义对应的关联字段,因此抛出找不到关联键的错误。
解决办法
提供三种可行的解决思路:
1. 扁平化查询逻辑(推荐)
直接沿用第一个正常运行的代码结构,避免在查询中间构造包含集合属性的自定义类,让LinqToDB可以正常解析查询逻辑:
var results97 = (from record in x.Psi.Psiproductparts from infoRecord in record.Programpressinforecords select new ES_WONPROGRAMPRESSINFORMATIONRECORD() { record_title = infoRecord.PpiTitle }.record_title).ToArray();
2. 切换到内存查询构造载体类
如果必须使用ES_PRODUCT作为中间载体,可以通过AsEnumerable()将外层查询切换到内存中执行,避免LinqToDB解析ES_PRODUCT的关联逻辑:
var results97 = (from record in x.Psi.Psiproductparts.AsEnumerable() let bar = new ES_PRODUCT { p_product_programpressinformationrecords = from infoRecord in record.Programpressinforecords select new ES_WONPROGRAMPRESSINFORMATIONRECORD() { record_title = infoRecord.PpiTitle } } from infoRecord2 in bar.p_product_programpressinformationrecords select infoRecord2.record_title).ToArray();
注意:这种方式会将Psiproductparts的所有数据拉取到内存中,数据量较大时可能影响性能,需谨慎使用。
3. 标记类为非数据库表
给ES_PRODUCT添加LinqToDB的[NotTable]特性,明确告知框架该类不是数据库表,无需处理关联逻辑:
using LinqToDB.Mapping; [NotTable] class ES_PRODUCT { public IEnumerable<ES_WONPROGRAMPRESSINFORMATIONRECORD>? p_product_programpressinformationrecords { get; set; } }
修改后,原查询代码即可正常运行。
内容的提问来源于stack exchange,提问作者MrD at KookerellaLtd
相关产品推荐
相关产品推荐

