Не удается извлечь записи, не являющиеся общими

#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:

У вас нет прямого способа извлечь записи, которые не являются общими. Но что вы могли бы сделать, это

  1. Получить principalobjectaccess, где относительно записи является учетная запись или контакт или так далее
  2. Таким образом, у вас будут все учетные записи / контакты, которые являются общими.
  3. Теперь выполните итерацию по всем учетным записям / контактам и проверьте, совпадает идентификатор, который вы извлекли из principalobjectaccess, или нет
  4. Таким образом, вы могли бы получить список или учетную запись / контакт (записи), которые не являются общими

    введите описание изображения здесь

Комментарии:

1. Все верно. Я должен попробовать этот способ. У меня большой набор данных.

2. @Nachiket Пожалуйста, дайте мне знать, если это поможет решить вашу проблему.

Ответ №2:

Я проверил базу данных, и PrincipleTypeCode это код ObjectTypeCode, сохраненный как int , а не как string .

principalTypeCode

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 это может быть сделано в одном вложенном запросе 🙂