触发器查询中动态传入ContentDocument ID过滤无结果的问题
嘿,我之前也踩过动态查询ContentDocumentLink的坑,结合你的需求和问题,咱们来一步步排查解决:
首先解决动态传入ContentDocumentId无结果的问题
大概率是查询格式或变量绑定的问题,给你几个排查方向:
确保变量绑定正确,不要直接字符串拼接ID
硬编码能查到是因为格式完全正确,但动态传入时如果直接把ID拼进SOQL字符串,很容易因为引号、数据类型问题出错。推荐用绑定变量(带:前缀)的方式,既安全又不会出错:// 正确的绑定方式(静态SOQL) ID targetDocId = 你动态获取的ID; // 确保是ID类型,不是字符串 List<ContentDocumentLink> cdlList = [ SELECT Id, LinkedEntityId FROM ContentDocumentLink WHERE LinkedEntity.Type = '你的自定义对象API名称__c' AND ContentDocumentId = :targetDocId ];如果是动态构建SOQL,同样要用绑定变量:
String customObjApiName = '你的自定义对象API名称__c'; ID targetDocId = 你动态获取的ID; String query = 'SELECT Id FROM ContentDocumentLink WHERE LinkedEntity.Type = :customObjApiName AND ContentDocumentId = :targetDocId'; List<ContentDocumentLink> cdlList = Database.query(query);检查LinkedEntity.Type的正确性
确认自定义对象的API名称是带__c后缀的,比如你的对象叫Contract__c,就不能写成Contract。硬编码时可能你写对了,但动态传入的类型变量可能拼错了,这也会导致查询无结果。验证动态传入的ID确实关联了目标自定义对象
有时候动态获取的ID对应的文件,可能根本没和你的自定义对象关联,自然查不到结果。可以单独执行以下查询确认:ID testDocId = 你动态传入的ID; List<ContentDocumentLink> allLinks = [SELECT LinkedEntity.Type FROM ContentDocumentLink WHERE ContentDocumentId = :testDocId]; for(ContentDocumentLink link : allLinks) { System.debug('当前文件关联的对象类型:' + link.LinkedEntity.Type); }看看输出里有没有你的目标自定义对象类型。
解决完查询问题后,实现「仅角色名含文件名的用户可见」的需求
查询到正确的ContentDocumentLink后,你需要把文件设为私有,再手动分享给符合条件的用户:
先把文件设为私有
修改ContentDocumentLink的Visibility字段为'Private',这样默认只有所有者能访问:if(!cdlList.isEmpty()) { ContentDocumentLink cdl = cdlList[0]; cdl.Visibility = 'Private'; update cdl; }查询符合条件的用户(角色名包含文件名)
先获取文件的标题(文件名),再筛选角色名包含该标题的用户:ContentDocument doc = [SELECT Title FROM ContentDocument WHERE Id = :targetDocId]; String fileName = doc.Title; List<User> eligibleUsers = [ SELECT Id FROM User WHERE Profile.UserRole.Name LIKE '%' + fileName + '%' AND IsActive = true ];给这些用户创建分享记录
通过ContentDocumentShare对象给符合条件的用户添加访问权限:List<ContentDocumentShare> shares = new List<ContentDocumentShare>(); for(User u : eligibleUsers) { ContentDocumentShare shareRec = new ContentDocumentShare(); shareRec.ContentDocumentId = targetDocId; shareRec.UserOrGroupId = u.Id; shareRec.AccessLevel = 'View'; // 可以设为'Edit'给编辑权限 shareRec.RowCause = 'Manual'; shares.add(shareRec); } if(!shares.isEmpty()) { insert shares; }
这样就能实现你要的「仅角色名称包含文件名的用户可见私有文件」的需求啦!
内容的提问来源于stack exchange,提问作者Zee S

