#c# #dynamics-crm #dynamics-365 #query-expressions
#c# #dynamics-crm #dynamics-365 #выражения запроса
Вопрос:
У меня есть сценарий, позволяющий найти записи, которые не являются общими для access team.
QueryExpression query = new QueryExpression("task")
{
ColumnSet = new ColumnSet("activityid", "subject", "customid"),
Criteria = new FilterExpression()
{
Conditions =
{
new ConditionExpression("customid", ConditionOperator.NotNull)
}
},
LinkEntities =
{
new LinkEntity("task", "principalobjectaccess", "activityid", "objectid", JoinOperator.Inner)
{
Columns = new ColumnSet(true),
EntityAlias = "POA",
LinkCriteria = new FilterExpression()
{
Conditions =
{
new ConditionExpression("principaltypecode", ConditionOperator.NotEqual, "team")
}
}
}
}
};
Результат содержит записи, которые являются общими и не являются общими.
значение principaltypecode содержит либо SystemUser, либо Team, в моем сценарии я ожидаю записи, которые не являются общими ни с одной командой.
Обновление: в XrmToolbox есть один плагин, который помог мне найти записи, не являющиеся общими.
В этом плагине есть ответ на мой вопрос, но для этого мне нужен код на c #. Кто-нибудь знает механизм этого инструмента для поиска таких записей?
Комментарии:
1. я бы предположил, что таблица POA содержит только записи, которые являются общими…..
2. Для каждой записи в таблице POA всегда будет 1 запись, поскольку при создании записи она будет доступна пользователю-владельцу. Если мы поделимся записью с team, в POA будет создана еще 1 запись. Теперь я должен извлечь записи, которые являются общими для team, и вычесть их из всех записей в базе данных. Это единственный выход, который я вижу здесь.
3. Плагин @Nachiket XrmToolbox использует решение 1, которое я опубликовал в своем ответе ниже. Вы можете проверить это с помощью fiddler или другого подобного веб-инструмента отладки.
Ответ №1:
У вас нет прямого способа извлечь записи, которые не являются общими. Но что вы могли бы сделать, это
- Получить principalobjectaccess, где относительно записи является учетная запись или контакт или так далее
- Таким образом, у вас будут все учетные записи / контакты, которые являются общими.
- Теперь выполните итерацию по всем учетным записям / контактам и проверьте, совпадает идентификатор, который вы извлекли из principalobjectaccess, или нет
-
Таким образом, вы могли бы получить список или учетную запись / контакт (записи), которые не являются общими
Комментарии:
1. Все верно. Я должен попробовать этот способ. У меня большой набор данных.
2. @Nachiket Пожалуйста, дайте мне знать, если это поможет решить вашу проблему.
Ответ №2:
Я проверил базу данных, и PrincipleTypeCode
это код ObjectTypeCode, сохраненный как int
, а не как string
.
8 — это код типа объекта для SystemUser
9 — это код типа объекта для Team
principaltypecode
никогда не должно быть равно «team», поэтому ваш текущий запрос возвращает все.
Возможно, вы захотите попробовать:
new ConditionExpression("principaltypecode", ConditionOperator.NotEqual, 9)
Комментарии:
1. Это не работает. Вы по-прежнему будете получать задачи, которые были общими как для пользователей, так и для команд.
2. Какие значения содержатся в PrincipalTypeCode? Не должно быть 9-х. В худшем случае вы можете отфильтровать их после извлечения.
3. Команда или пользователь. Дело в том, что если запись доступна как пользователю, так и команде, в таблице POA будет 2 записи, одна для пользователя и одна для команды. Таким образом, при использовании notequal to 9 запрос все равно получит задачу, общую для обоих, потому что у нее будет запись в таблице POA, не связанная с PrincipalTypeCode 9.
4. Хорошо, это имеет смысл. С моей точки зрения, я не уверен, что запрос может выполнять то, что вы хотите. Возможно, вам нужно выполнить существующий запрос, а затем выполнить дальнейшую фильтрацию в коде. Я делаю это постоянно в консольных приложениях — извлекаю наборы данных и обрабатываю в оперативной памяти. LINQ очень удобен для такого рода вещей.
5. Да, я исправлю код. Что, если я найду записи задач, у которых нет записи в таблице POA? сработает ли это в моем случае?
Ответ №3:
Решение 1
Выполните левое внешнее соединение между Task и таблицей POA, извлекая только столбец acitivityId и столбец principaltypecode:
var query = new QueryExpression("task");
var principalObjectAccess = query.AddLink("principalobjectaccess", "activityid", "objectid", JoinOperator.LeftOuter);
principalObjectAccess.Columns.AddColumns("principaltypecode");
var entityCollection = _service.RetrieveMultiple(query);
Затем выполните фильтрацию в памяти, чтобы удалить все записи в коллекции, где principaltypecode равен team. Помните, что если вы найдете идентификатор, который удовлетворяет этому условию, вам придется удалить все записи с этим идентификатором, это важно для удаления задач, которые являются общими как для пользователя, так и для команды.
Решение 2
Этот запрос предоставит вам все задачи, которые являются общими для команды:
var teamPrincipalTypeCode = 9;
var query = new QueryExpression("task");
var principalObjectAccess = query.AddLink("principalobjectaccess", "activityid", "objectid");
principalObjectAccess.LinkCriteria.AddCondition("principaltypecode", ConditionOperator.Equal, teamPrincipalTypeCode);
var entityCollection = _service.RetrieveMultiple(query);
После запуска вам просто нужно запросить все идентификаторы guid задачи и вычесть те, которые были возвращены приведенным выше запросом. Вы можете легко сделать это, используя метод Except из System.Пространство имен Linq.
Комментарии:
1. Это имеет смысл. Выполнение этого займет некоторое время и может оказаться невыполнимым для большого набора данных.
2. @Nachiket К сожалению, FetchXML не так богат, как SQL. В SQL это может быть сделано в одном вложенном запросе 🙂