24.11.2008, 11:07 | #1 |
Чайный пьяница
|
Создание и регистрация плагина на Execute и Retreive
Задача, которая была поставлена - необходимо было в целочисленные поля new_hour и new_min сущности new_task - возвращать часы и минуты в работе с задачей соответственно. Механику вычисления - пропущу, потому как она для каждого отдельного случая может быть уникальна.
1. Особенности регистрации - плагин на Execute (в моём случае я отслеживал получение данных в гриды MS CRM) необходимо регистрировать на Post Event не выбирая сущность и поля. Плагин на Retreive - необходимо регистрировать на Post Event, указывая имя сущности. 2. Особенности реализации: Execute: Код: public override void Execute(IPluginExecutionContext context) { //метод для получения строки подключения к базе MS CRM будет приведён ниже string sqlConnectionString = GetSqlConnectionString(context.OrganizationName); //контролируем, что было событие Execute и Возвоащается FetchXml if (context.MessageName == "Execute" && context.InputParameters.Contains("FetchXml")) { XmlDocument indoc = new XmlDocument(); indoc.LoadXml((string)context.InputParameters["FetchXml"]); //контролируем имя сущности поиск по которой был выполнен entityName = indoc.SelectSingleNode("//fetch/entity").Attributes["name"].InnerText; if (entityName != "new_task") return; //получаем Xml, который возвращается на сторону клиента XmlDocument outdoc = new XmlDocument(); outdoc.LoadXml((string)context.OutputParameters["FetchXmlResult"]); foreach (XmlNode node in outdoc.SelectNodes("//resultset/result")) { Guid recordId = new Guid(node.SelectSingleNode("./new_taskid").InnerText); //чтобы не путать читателя кода поясню - GetWorkingMinutesCount - метод, который зачитывает данные из MS SQL сервера //в данном случае - время выполнения задачи в минутах calcMinCount = GetWorkingMinutesCount(recordId, sqlConnectionString); XmlNode hoursnode = node.SelectSingleNode("./new_hour"); if (hoursnode != null) { hoursnode.Attributes["formattedvalue"].Value = hoursnode.InnerText = ((int)(calcMinCount / 60)).ToString(); } XmlNode minsnode = node.SelectSingleNode("./new_mins"); if (minsnode != null) { minsnode.Attributes["formattedvalue"].Value = minsnode.InnerText = ((int)(calcMinCount % 60)).ToString(); } } //возвращаем на клиента уже отформатированный Xml context.OutputParameters["FetchXmlResult"] = outdoc.OuterXml; } } Код: public override void Execute(IPluginExecutionContext context) { if (context.MessageName == "Retrieve") { entityName = context.PrimaryEntityName; //контролирую имя сущности, получение которой ведётся при помощи Retreive - например при открытии карточки if (entityName != "new_task") return; DynamicEntity currentEntity = (Microsoft.Crm.Sdk.DynamicEntity)context.OutputParameters.Properties["BusinessEntity"]; if (!currentEntity.Properties.Contains("new_hour") && !currentEntity.Properties.Contains("new_mins")) return; Guid recordId = ((Microsoft.Crm.Sdk.Key)currentEntity.Properties["new_taskid"]).Value; string sqlConnectionString = GetSqlConnectionString(context.OrganizationName); int calcMinCount = GetWorkingMinutesCount(recordId, sqlConnectionString); if (currentEntity.Properties.Contains("new_hour")) ((CrmNumber)currentEntity.Properties["new_hour"]).Value = calcMinCount / 60; if (currentEntity.Properties.Contains("new_mins")) ((CrmNumber)currentEntity.Properties["new_mins"]).Value = calcMinCount % 60; } } Код: protected string GetSqlConnectionString(string orgname) { RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\MSCRM"); //Retreive MSCRM DataBase connection string string configDBConnectionString = key.GetValue("configdb").ToString(); //next part - i connect to config db and retreive data to config connection to client db DataSet clientDBConnectionData = new DataSet(); using (SqlConnection connection = new SqlConnection(configDBConnectionString)) { connection.Open(); using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = connection; cmd.CommandType = CommandType.Text; cmd.CommandText = string.Format("Select SqlServerName, DatabaseName From Organization Where UniqueName = '{0}'", orgname); using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) adapter.Fill(clientDBConnectionData); } connection.Close(); } if (clientDBConnectionData.Tables.Count == 0 || clientDBConnectionData.Tables[0].Rows.Count == 0) throw new Exception("Check your config parameters!"); string connectionString = string.Format("Data Source={0};Initial Catalog={1};Integrated Security=SSPI", new object[] { (string)clientDBConnectionData.Tables[0].Rows[0]["SqlServerName"], (string)clientDBConnectionData.Tables[0].Rows[0]["DatabaseName"]}); return connectionString; } Последний раз редактировалось a33ik; 24.11.2008 в 11:20. |
|
24.11.2008, 12:36 | #2 |
Moderator
|
Читать строку коннекции SQL из реестра, а так же делать прямые запросы - жесткий ансапорт! Перебирать XML... зачем такие сложности!!?? Используйте готовые сервисы!
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
24.11.2008, 15:09 | #3 |
Чайный пьяница
|
Цитата:
PS - для себя. О каких готовых сервисах идёт речь? Список ансапортеда - http://msdn.microsoft.com/en-us/library/bb928224.aspx и запросов к базе там ну нет. Структуру базы я не меняю. Последний раз редактировалось a33ik; 24.11.2008 в 15:18. |
|
28.11.2008, 19:21 | #4 |
Участник
|
|
|
28.11.2008, 20:02 | #5 |
Заноза в заднице
|
В целом, конечно право имеет, но есть вопросы:
1. "SOFTWARE\\Microsoft\\MSCRM" - разве не хард-код? Здесь намного правильнее было бы создать центральную консоль управления плагинами, в которой отдельными полями хранить данные о строке подключения и прочих разных параметрах. Данные об этом уместно складывать в веб-конфиг - он для того и предназначен. А лезть в реестр может только тот, у кого есть соответствующие права. У нас, например, правила безопасности таковы, что кто попало не имеет прав на читку реестра, даже если он админ в системе CRM. 2. Использование CrmService вызывает отторжение что-ли, я не пойму? С помощью CrmService можно выполнить все те же операции, приемлемыми для системы методами. К тому же, я полагаю, что скорость обработки будет гораздо быстрее.
__________________
Лень мудрого человека - это необходимое средство нейтрализации кипучей активности руководящих им дураков! |
|
28.11.2008, 22:18 | #6 |
Moderator
|
Да незачем ее брать! Есть CrmService которым надо пользоваться! Помню помню, что для весьма специфичных задач он не подходит, но, как я уже говорил большинство из них преодолимо.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
30.11.2008, 01:25 | #7 |
Чайный пьяница
|
Цитата:
Насчёт скорости - 100% быстрее будет работать прямой запрос, потому что звено короче на 1 - на веб сервис. Объясню, почему я ушёл от работы с веб сервисами. Механизм джоинов - конечно при работе с веб сервисами есть - через фетч и линкд ентити и прочее, но оно настолько громоздкое и нетривиальное, что для меня - как разработчика было проще написать прямой запрос к базе. |
|
30.11.2008, 15:03 | #8 |
Moderator
|
С этим согласен - механизм построения запросов у Microsoft неимоверно убогий. Кто работал с Oracle TopLink меня поймет...
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|