RavenDB从3.x迁移至5.x后Linq转RQL生成多余id()问题求助
问题根因
RavenDB 4.x及后续版本的LINQ查询转换器对接口类型的属性识别逻辑与3.x版本存在差异:你调用RavenQuery.Load<IGroup>(onboarding.Group.DocumentId)时,Group的类型是IGroup接口,转换器无法通过你配置的全局FindIdentityProperty约定识别接口下的DocumentId为身份字段,会默认将onboarding.Group判定为关联文档对象,自动加上id()方法取其标识,导致传入参数错误。
而后续((Team)onboradGroup).Site.DocumentId因为Team是实体类,转换器可以正常识别到DocumentId的身份属性约定,所以不会额外生成id()包裹。
可行解决方案
你可以任选以下任意一种方式处理:
- 方案1:为接口类型显式注册身份属性约定
在初始化DocumentStore的阶段,除了全局的FindIdentityProperty约定,额外为用到的接口类型注册身份识别规则,代码如下:
注册后转换器就能正确识别接口下的documentStore.Conventions.FindIdentityPropertyForType = (type, memberInfo) => { if (typeof(IGroup).IsAssignableFrom(type) || typeof(IOnboarding).IsAssignableFrom(type)) { return memberInfo.Name == "DocumentId"; } return documentStore.Conventions.FindIdentityProperty(memberInfo); };DocumentId字段,不会自动加id()包裹。 - 方案2:强制指定Load入参为字符串ID
在RavenQuery.Load的入参位置显式强转为字符串,阻断转换器的实体关联推断逻辑:
该方式无需修改全局配置,只需要调整对应查询的写法即可生效。let onboradGroup = RavenQuery.Load<IGroup>((string)onboarding.Group.DocumentId) let invitedBy = RavenQuery.Load<User>((string)onboarding.InvitedByUser.DocumentId) - 方案3:直接使用原生RQL查询
如果复杂查询的LINQ转换不符合预期,可以直接通过会话的原生查询接口手写RQL,完全控制生成的查询逻辑:var query = documentSession.Advanced.RawQuery<T>(@" declare function output(result, onboarding) { var onboradGroup = load(onboarding.Group.DocumentId); var invitedBy = load(onboarding.InvitedByUser.DocumentId); var siteDoc = load(onboradGroup.Site.DocumentId); return { ... }; } from index 'Onboardings/All' as result load result.OnboardingDocumentId as onboarding select output(result, onboarding) ");
所有方案修改完成后,可以调用query.ToString()输出生成的RQL语句,确认id()包裹逻辑已被移除后再上线验证即可。
内容的提问来源于stack exchange,提问作者amir
相关产品推荐
相关产品推荐

