AXForum  
Вернуться   AXForum > Microsoft Dynamics CRM > Dynamics CRM: Разработка
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.04.2011, 11:35   #1  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
SOAP-запрос для получения списка записей N:N
Здравствуйте. У меня возник такой вопрос. Можно ли при помощи SOAP-запроса получить список записей, связанных отношением N;N с данной?
Старый 11.04.2011, 11:43   #2  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Без проблем. Можно использовать как fetch так и retrive запросы. N:N - это, фактически два отношения 1:N с промежуточной сущностью, которая называется объект пересечения. Имя этого объекта можно посмотреть в настройках связи. Объект пересечения содержит пары идентификаторов связанных сущностей, так что вам, фактически нужно выбрать все экземпляры объекта пересечения, которые ссылаются на вашу сущность. Так вы получите список записей второго объекта, связанного с ней.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional

Последний раз редактировалось Артем Enot Грунин; 11.04.2011 в 11:45.
Старый 11.04.2011, 11:48   #3  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Вот нашел у себя в коде функцию:
Код:
var oTypeThis = crmForm.ObjectTypeCode;
var oTypeThisName = crmForm.ObjectTypeName;
var oTypeAssociated = Product;
var oTypeAssociatedName = "product";
var oAssociationName = "new_productsForLead";
var oAssociationRecordName = "new_productsforlead";


function getAssociatedRecordsIds()
{
    var oFetchXML =    "<fetch mapping='logical'>" +
                "<entity name='" + oAssociationRecordName + "'>" +
                    "<attribute name='" + oTypeAssociatedName + "id'/>" +
                    "<filter type='and'>" +
                        "<condition attribute='" + oTypeThisName + "id' operator='eq' value='" + crmForm.ObjectId + "'/>" +
                    "</filter>" +
                "</entity>" +
            "</fetch>";

        oFetchXML = oFetchXML.replace(/</g, '&lt;');
        oFetchXML = oFetchXML.replace(/>/g, '&gt;');

    var oSOAP =    "<?xml version='1.0' encoding='utf-8'?>"+ 
            "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'" +
                        " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +
                        " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" + 
                GenerateAuthenticationHeader() + 
                "<soap:Body>" + 
                    "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" + 
                        "<fetchXml>" +
                            oFetchXML +
                        "</fetchXml>" + 
                    "</Fetch>"+ 
                "</soap:Body>"+ 
            "</soap:Envelope>";

    var oXmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    oXmlHttp.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    oXmlHttp.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
    oXmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    oXmlHttp.setRequestHeader("Content-Length", oSOAP.length);
    oXmlHttp.send(oSOAP);

    var oResponseText = oXmlHttp.responseXML.text;

    var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    oXmlDoc.async = false; 
    oXmlDoc.loadXML(oResponseText);

    var results = oXmlDoc.getElementsByTagName(oTypeAssociatedName + "id");
    var associatedRecordsIds = new Array(results.length);

    for (var i = 0; i < results.length; i++)
    {
        associatedRecordsIds[i] = results[i].text;
    }
    return associatedRecordsIds;
}
Надеюсь это то что нужно. В принципе должно работать и с несистемными N:N отношениями, но возможно с рядом модификаций.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
За это сообщение автора поблагодарили: Skyway (1).
Старый 11.04.2011, 12:20   #4  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
Спасибо! Как раз то что нужно. Все заработало с первого раза.
Старый 11.04.2011, 12:25   #5  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Пожалуйста, вот оригинальный пост: http://www.axforum.info/forums/blog.php?b=46, возможно вам пригодится еще что-то из изложенного функционала.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
За это сообщение автора поблагодарили: Skyway (1).
Старый 18.04.2011, 09:01   #6  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
Возник еще один вопрос по схожей теме. Нужно написать FetchXML - запрос, который возвращает только свои записи, если роль текущего пользователя "Сотрудник", и все записи в противном случае. При этом определение принадлежности записи пользователю происходит на основе значения поля new_person, а не на основе ownerid. Возможно ли написать такой запрос?

Последний раз редактировалось Skyway; 18.04.2011 в 09:29.
Старый 18.04.2011, 11:09   #7  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Да, но для этого потребуется 2-3 запроса.
1. Получить идентификатор пользователя (WhoAmI).
2. Вычитать роли пользователя с нужным названием
3. Сделать выводы и построить нужный запрос.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
Старый 18.04.2011, 11:37   #8  
a33ik is offline
a33ik
Чайный пьяница
Аватар для a33ik
MCP
MCBMSS
Злыдни
Соотечественники
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,243 / 896 (36) +++++++
Регистрация: 02.07.2008
Адрес: Greenville, SC
Цитата:
Сообщение от Артем Enot Грунин Посмотреть сообщение
Да, но для этого потребуется 2-3 запроса.
1. Получить идентификатор пользователя (WhoAmI).
2. Вычитать роли пользователя с нужным названием
3. Сделать выводы и построить нужный запрос.
1 и 2 можно вообще то объединить. Есть же оператор EqualUserId, если не ошибаюсь. Ну и скрипт есть готовый - http://jianwang.blogspot.com/2008/01...-security.html
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством.

Подписывайтесь на мой блог, twitter и YouTube канал.
Пользуйтесь моим Ultimate Workflow Toolkit
Старый 18.04.2011, 11:47   #9  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
Вообще, FetchXML мне нужен для создания представления, то есть javascript, как я понимаю, там нельзя использовать.Представление будет создаваться при помощи плагина, который описан здесь: http://mmcrm.ru/?p=1531
Можно ли использовать несколько запросов при помощи данного способа?
Старый 18.04.2011, 11:56   #10  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Верно! Я почему-то подумал, что для нестандартного поля в пункте 3 EqualUserId не сработает.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
Старый 18.04.2011, 12:01   #11  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Цитата:
Сообщение от Skyway Посмотреть сообщение
Вообще, FetchXML мне нужен для создания представления, то есть javascript, как я понимаю, там нельзя использовать.Представление будет создаваться при помощи плагина, который описан здесь: http://mmcrm.ru/?p=1531
Можно ли использовать несколько запросов при помощи данного способа?
Это не плагин, а консольное приложение, которое создает статическое представление. В вашем случае придется использовать именно плагин: http://www.axforum.info/forums/blog.php?b=173
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
Старый 19.04.2011, 16:31   #12  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
Ну да, приложение, это была описка)
Пытаюсь тут разобраться с плагином. Хочу чтобы выполнялся хотябы простой запрос. Создал новое представление, в описании написал new_business_trip.all, поменял плагин следующим образом:
X++:
using System;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using System.Data.SqlClient;
using Microsoft.Crm.Sdk.Query;

namespace CustomQueryAPI
{
    public class QueryFetchPlugin : IPlugin
    {
        private string connectionString;
        IPluginExecutionContext pluginContext;

        public QueryFetchPlugin(string unsecure, string secure)
        {
            //"Data Source=CRMDEV;Initial Catalog=ICS_MSCRM;Integrated Security=SSPI"
            connectionString = secure;
        }

        public void Execute(IPluginExecutionContext context)
        {
            this.pluginContext = context;

            DynamicEntity query = (DynamicEntity)pluginContext.OutputParameters[ParameterName.BusinessEntity];
            string api = (string)query.Properties["description"];
            if (String.IsNullOrEmpty(api)) return;

            // Для систематизации и удобства наращивания api группируются в наборы ClassAPI.MetodAPI
            string[] paths = api.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
            if (paths.Length < 2) return;



            string className = paths[0];
            string methodName = paths[1];

            string myFetch = String.Empty;

            switch (className)
            {
                case "New_business_trip":
                    myFetch = retrieveBusinessTrip(methodName);
                    break;
            }

            if (myFetch != null) query.Properties["fetchxml"] = myFetch;
        }

        private string queryExpressionToFetch(QueryBase query)
        {
            QueryExpressionToFetchXmlRequest request = new QueryExpressionToFetchXmlRequest();
            request.Query = query;

            ICrmService service = this.pluginContext.CreateCrmService(true);
            QueryExpressionToFetchXmlResponse responce = (QueryExpressionToFetchXmlResponse)service.Execute(request);

            return responce.FetchXml;
        }


        private string sqlToFetch(string entity, string primarykey, string sql)
        {
            string fetchPattern = @"<fetch version=""1.0"" output-format=""xml-platform"" mapping=""logical"" distinct=""false"">
                                            <entity name=""{0}"">
                                                <attribute name=""{1}""/>
                                                <filter type=""and"">
                                                    <condition attribute=""{1}"" operator=""in"">
                                                            {2}
                                                    </condition>
                                                </filter>
                                            </entity>
                                    </fetch>";

            string filterValues = String.Empty;

            using (SqlConnection sqlConnection = new SqlConnection(this.connectionString))
            {
                sqlConnection.Open();
                SqlCommand cmd = new SqlCommand(sql, sqlConnection);

                SqlDataReader reader = cmd.ExecuteReader();
                try
                {
                    while (reader.Read())
                    {
                        string id = ((Guid)reader[0]).ToString();
                        filterValues += "<value>" + id + "</value>\n";
                    }
                }
                finally
                {
                    reader.Close();
                }

            }
            return String.Format(fetchPattern, entity, primarykey, filterValues);
        }

 
        private string retrieveBusinessTrip(string methodName)
        {
            string fetch = String.Empty;
            switch (methodName)
            {
                case "all":
                    string sqlQuery = "SELECT new_business_tripid FROM new_business_trip Where new_name like 'г%'";
                    fetch = sqlToFetch("new_business_trip", "new_business_tripid", sqlQuery);
                    break;
            }
            return fetch;
        }

    }
}
Зарегистрировал Pre Stage, событие Retrive, сущность UserQuery.
Но почему-то ничего не происходит, такое впечатление что плагин не работает.
Старый 19.04.2011, 16:42   #13  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Отлаживаться пробовали? При регистрации плагина указывалась строка соединения в параметре secure?
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
Старый 21.04.2011, 09:42   #14  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
Да, строку соединения указал. Отлаживать пытался, с этим какая-то проблема - отладчик не вызывается о_О
За все время моих попыток он вызвался единственный раз, и сработало исключение на этой строчке:
DynamicEntity query = (DynamicEntity)pluginContext.OutputParameters[ParameterName.BusinessEntity];
Исключение по поводу неправильности ключа (Invalid или Null, я точно не запомнил).
Непонятна логика срабатывания плагина(или отладчика). Как я понял, вызов должен происходить при просмотре любого представления?
Старый 21.04.2011, 16:33   #15  
Skyway is offline
Skyway
Участник
 
78 / 10 (1) +
Регистрация: 07.08.2009
В результате как я понял происходит что-то вроде кеширования, то есть плагин начинает работать не сразу после регистрации, а по прошествии достаточно продолжительного количества времени. Кто-нибудь сталкивался с этим? iisreset не помогает.

Ошибка следующая: "The given key not present in the dictionary" в этой строке:
DynamicEntity query = (DynamicEntity)pluginContext.OutputParameters[ParameterName.BusinessEntity];
Старый 21.04.2011, 22:34   #16  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Вы знаете, я бы не выложил бы код, если бы не был уверен, что он работает. Возможно вы все же указали какие-то другие параметры при регистрации, или зарегистрировали плагин не на то событие? Я как раз сегодня читал лекцию по плагинам и мы с группой смотрели как в Output параметрах возвращается объект который должно вернуть событие. В случае Retrive это должен быть объект BusinessEntity. Ума не приложу, почему его может не быть в этом событии. Пожалуйста проверьте еще раз все ли правильно вы настроили.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional
Старый 21.04.2011, 22:50   #17  
Konstantin Katsovich is offline
Konstantin Katsovich
Участник
Аватар для Konstantin Katsovich
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
243 / 57 (2) ++++
Регистрация: 22.10.2008
Адрес: Israel
Цитата:
Сообщение от Skyway Посмотреть сообщение
В результате как я понял происходит что-то вроде кеширования, то есть плагин начинает работать не сразу после регистрации, а по прошествии достаточно продолжительного количества времени. Кто-нибудь сталкивался с этим? iisreset не помогает.
У меня отладка Вашего плагина и плагина Артема срабатывает при каждом вызове.
Проблем со срабатывание не наблюдаются. Посмею предположить что Вы регистрируете плагин в базе. Если да попробуйте на диске.
Цитата:
Сообщение от Skyway Посмотреть сообщение
Ошибка следующая: "The given key not present in the dictionary" в этой строке:
DynamicEntity query = (DynamicEntity)pluginContext.OutputParameters[ParameterName.BusinessEntity];

По поводу ошибки.
У меня OutputParameters пустой. Поэтому мы и получаем ошибку.
(Проверял на разных сущностях системных, не системных)
P. S. Возможно после установке очередного ролапа эта возможность просто пропала.
__________________
Читайте SDK!!!
За это сообщение автора поблагодарили: Skyway (1).
Старый 21.04.2011, 23:06   #18  
Konstantin Katsovich is offline
Konstantin Katsovich
Участник
Аватар для Konstantin Katsovich
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
243 / 57 (2) ++++
Регистрация: 22.10.2008
Адрес: Israel
Переместив плагин на PostRetrieve код заработал как положено.
__________________
Читайте SDK!!!
Старый 21.04.2011, 23:54   #19  
Артем Enot Грунин is offline
Артем Enot Грунин
Moderator
Аватар для Артем Enot Грунин
MCBMSS
Злыдни
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,912 / 623 (28) +++++++
Регистрация: 16.08.2007
Адрес: Пермь!
Записей в блоге: 151
Ну, мог и опечататься Вообще пре-событие происходит до обработки внутри системной транзакции, так что пока система не вкурила что ее дурят, нужно выполнить нашу подмену. Либо действительно несовпадение версий, либо я что-то напутал.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия.

MS Certified Dirty Magic Professional

Последний раз редактировалось Артем Enot Грунин; 21.04.2011 в 23:59.
Теги
javascript, soap, связь n:n

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Помогите написать SOAP запрос kolya.master Dynamics CRM: Разработка 8 01.12.2009 16:47
SOAP и Join slivka_83 Dynamics CRM: Разработка 3 08.06.2009 10:13
Как создать экземпляр кастомной сущности через SOAP? Tony Green Dynamics CRM: Разработка 7 27.02.2009 08:37
Фильтр для отчета - из списка связанных записей? AlekseyS Dynamics CRM: Разработка 3 11.09.2008 10:54
Добавление из списка существующих записей Boris Ilyin Dynamics CRM: Функционал 1 09.02.2007 08:34

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 20:37.