无法获取未共享记录:求C#实现查找未与访问团队共享的Task记录
Let's start by breaking down why your original query isn't giving you the results you want:
- You’re using an
Inner Joinwithprincipalobjectaccess, which only returns tasks that have been shared with someone (either users or teams). This filters out tasks that haven’t been shared at all. - Adding
principaltypecode != teamjust excludes team-sharing entries, but still includes tasks shared with users (since those entries haveprincipaltypecode = SystemUser).
To get tasks that are not shared with any teams (including tasks that haven’t been shared with anyone at all), you need to use a NOT EXISTS condition to exclude any task that has a matching entry in principalobjectaccess for a team.
Correct QueryExpression Code
QueryExpression query = new QueryExpression("task") { ColumnSet = new ColumnSet("activityid", "subject", "customid"), Criteria = new FilterExpression { Conditions = { new ConditionExpression("customid", ConditionOperator.NotNull) }, FilterOperator = LogicalOperator.And, Filters = { new FilterExpression(LogicalOperator.Not) { Conditions = { // Subquery checks if there's any team sharing entry for the task new ConditionExpression("activityid", ConditionOperator.InSubQuery, new QueryExpression("principalobjectaccess") { ColumnSet = new ColumnSet("objectid"), Criteria = new FilterExpression { Conditions = { new ConditionExpression("objectid", ConditionOperator.Equal, "{activityid}"), new ConditionExpression("principaltypecode", ConditionOperator.Equal, "team") } } }) } } } } };
Alternative Approach with Left Outer Join
You can also use a left outer join to achieve the same result by filtering out tasks that have no matching team-sharing entries:
QueryExpression query = new QueryExpression("task") { ColumnSet = new ColumnSet("activityid", "subject", "customid"), Criteria = new FilterExpression { Conditions = { new ConditionExpression("customid", ConditionOperator.NotNull), // Either no shared entries exist, or no team shared entries exist new ConditionExpression("POA.objectid", ConditionOperator.Null) }, FilterOperator = LogicalOperator.And }, LinkEntities = { new LinkEntity("task", "principalobjectaccess", "activityid", "objectid", JoinOperator.LeftOuter) { EntityAlias = "POA", LinkCriteria = new FilterExpression { Conditions = { new ConditionExpression("principaltypecode", ConditionOperator.Equal, "team") } } } } };
How XrmToolBox Plugins Typically Implement This
Most XrmToolBox plugins that find unshared records rely on the NOT EXISTS pattern (the first approach above). Here’s why:
- It directly targets your core requirement: exclude any record that has been shared with teams.
- It’s efficient because it avoids joining large datasets, instead using a subquery to check for the presence of team-sharing entries.
- Some plugins might add extra checks (like filtering out records owned by teams if needed), but the core logic for excluding shared-with-team records is almost always the NOT EXISTS subquery against
principalobjectaccess.
Content sourced from Stack Exchange, question author: Nachiket
相关产品推荐
相关产品推荐

