27.03.2012, 17:56 | #1 |
Участник
|
CRM 2011, вопрос по плагину
товарищи, добрый день!
подскажите, пожалуйста, по плагину.. он делает следующее - обновляет сущность new_zayavka, создает Заказ, прописывает в Заказ название, прайслист, валюту, клиента и заблокированы ли цены. Эта часть отрабатывает как надо. Но я захотел добавить еще и продукт в этот Заказ, вот тут-то мне Плагин и выдал ошибку "the parent id is missing". Плагин повешен на Update сущности new_zayavka, на Pre-validation. спасибо! X++: Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: The parent id is missing.Detail: <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts"> <ErrorCode>-2147220970</ErrorCode> <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" /> <Message>The parent id is missing.</Message> <Timestamp>2012-03-27T13:26:50.6738765Z</Timestamp> <InnerFault i:nil="true" /> <TraceText> [ClassLibrary7: CreateSalesOrder.Order] [64e3abde-0978-e111-af6d-000c29c05d09: CreateSalesOrder.Order: Update of new_zayavka] Order: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: The parent id is missing. ( Microsoft.Xrm.Sdk.OrganizationServiceFault). </TraceText> </OrganizationServiceFault> X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Query; using System.ServiceModel; using System.ServiceModel.Description; namespace CreateSalesOrder { public class Order : IPlugin { public void Execute(IServiceProvider serviceProvider) { ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); try { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); Entity record = (Entity)context.InputParameters["Target"]; if (record.LogicalName == "new_zayavka") { record["new_inn"] = "sdf"; record["new_name_nai"] = record["new_inn"]; Entity pricelevel = new Entity("pricelevel"); Entity currency = new Entity("transactioncurrency"); Entity account = new Entity("account"); bool vispricelocked = false; Entity salesorder = new Entity("salesorder"); salesorder["name"] = "TEST"; salesorder["pricelevelid"] = new EntityReference(pricelevel.LogicalName, new Guid("156ABFBD-3704-DF11-9297-005056C00008")); salesorder["transactioncurrencyid"] = new EntityReference(currency.LogicalName, new Guid("9E79B15D-1937-E111-A8B6-08002739EA86")); salesorder["customerid"] = new EntityReference(account.LogicalName, new Guid("46053320-E952-E111-81DB-000C29C05D09")); salesorder["ispricelocked"] = vispricelocked; // Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); service.Create(salesorder); Guid id_1 = new Guid(salesorder["salesorderid"].ToString()); Entity salesorderdetail = new Entity("salesorderdetail"); salesorderdetail["new_orda"] = new EntityReference("salesorder", id_1); Entity product = new Entity("product"); Entity uom = new Entity("uom"); salesorderdetail["productid"] = new EntityReference(product.LogicalName, new Guid("AC341411-4347-E111-9250-000C29C05D09")); salesorderdetail["uomid"] = new EntityReference(uom.LogicalName, new Guid("5D15C954-A08E-DB11-934C-000E0C6AB271")); IOrganizationServiceFactory serviceFactory1 = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service1 = serviceFactory1.CreateOrganizationService(context.UserId); service1.Create(salesorderdetail); } } catch (Exception ex) { tracingService.Trace("Order: {0}", ex.ToString()); throw; } } } } |
|
27.03.2012, 18:12 | #2 |
Чайный пьяница
|
Это потому что при создании salesorderdetail вы не заполнили поле salesorderid детали.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
28.03.2012, 09:30 | #3 |
Участник
|
a33ik, спасибо, исправил, но теперь он пишет, что это значение Null:
его надо отделить в другой плагин на post-operation? при выполнении плагина Заказ создается, но после этого CRM говорит, что salesorderdetail думает, что salesorderid из этой сущности Null X++: Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Attribute: salesorderid cannot be set to NULLDetail: <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts"> <ErrorCode>-2147220989</ErrorCode> <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" /> <Message>Attribute: salesorderid cannot be set to NULL</Message> <Timestamp>2012-03-28T05:19:56.3402878Z</Timestamp> <InnerFault i:nil="true" /> <TraceText> [ClassLibrary7: CreateSalesOrder.Order] [64e3abde-0978-e111-af6d-000c29c05d09: CreateSalesOrder.Order: Update of new_zayavka] Order: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Attribute: salesorderid cannot be set to NULL ( Microsoft.Xrm.Sdk.OrganizationServiceFault). </TraceText> </OrganizationServiceFault> X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Query; using System.ServiceModel; using System.ServiceModel.Description; namespace CreateSalesOrder { public class Order : IPlugin { public void Execute(IServiceProvider serviceProvider) { ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); try { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); Entity record = (Entity)context.InputParameters["Target"]; if (record.LogicalName == "new_zayavka") { record["new_inn"] = "sdf"; record["new_name_nai"] = record["new_inn"]; Entity pricelevel = new Entity("pricelevel"); Entity currency = new Entity("transactioncurrency"); Entity account = new Entity("account"); bool vispricelocked = false; Entity salesorder = new Entity("salesorder"); salesorder["name"] = "TEST"; salesorder["pricelevelid"] = new EntityReference(pricelevel.LogicalName, new Guid("156ABFBD-3704-DF11-9297-005056C00008")); salesorder["transactioncurrencyid"] = new EntityReference(currency.LogicalName, new Guid("9E79B15D-1937-E111-A8B6-08002739EA86")); salesorder["customerid"] = new EntityReference(account.LogicalName, new Guid("46053320-E952-E111-81DB-000C29C05D09")); salesorder["ispricelocked"] = vispricelocked; // Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); service.Create(salesorder); Guid id_1 = new Guid(salesorder["salesorderid"].ToString()); Entity salesorderdetail = new Entity("salesorderdetail"); salesorderdetail["new_orda"] = new EntityReference("salesorder", id_1); salesorderdetail["salesorderid"] = salesorder["salesorderid"]; Entity product = new Entity("product"); Entity uom = new Entity("uom"); salesorderdetail["productid"] = new EntityReference(product.LogicalName, new Guid("AC341411-4347-E111-9250-000C29C05D09")); salesorderdetail["uomid"] = new EntityReference(uom.LogicalName, new Guid("5D15C954-A08E-DB11-934C-000E0C6AB271")); IOrganizationServiceFactory serviceFactory1 = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service1 = serviceFactory1.CreateOrganizationService(context.UserId); service1.Create(salesorderdetail); } } catch (Exception ex) { tracingService.Trace("Order: {0}", ex.ToString()); throw; } } } } |
|
28.03.2012, 10:24 | #4 |
Чайный пьяница
|
Есть небольшая проблема - вы не оттуда получаете идентификатор salesorder. Попробуйте так:
Guid id_1 = service.Create(salesorder);
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
За это сообщение автора поблагодарили: mistah (1). |
28.03.2012, 11:28 | #5 |
Участник
|
a33ik, он, видимо, теперь считает, что я пытаюсь создать еще один Заказ:
X++: Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Cannot insert duplicate key.Detail: <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts"> <ErrorCode>-2147220937</ErrorCode> <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" /> <Message>Cannot insert duplicate key.</Message> <Timestamp>2012-03-28T07:23:18.3667022Z</Timestamp> <InnerFault i:nil="true" /> <TraceText> [ClassLibrary7: CreateSalesOrder.Order] [64e3abde-0978-e111-af6d-000c29c05d09: CreateSalesOrder.Order: Update of new_zayavka] Order: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Cannot insert duplicate key. ( Microsoft.Xrm.Sdk.OrganizationServiceFault). </TraceText> </OrganizationServiceFault> X++: IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); service.Create(salesorder); Guid id_1 = service.Create(salesorder); Entity salesorderdetail = new Entity("salesorderdetail"); salesorderdetail["new_orda"] = new EntityReference("salesorder", id_1); salesorderdetail["salesorderid"] = id_1; Entity product = new Entity("product"); Entity uom = new Entity("uom"); salesorderdetail["productid"] = new EntityReference(product.LogicalName, new Guid("AC341411-4347-E111-9250-000C29C05D09")); salesorderdetail["uomid"] = new EntityReference(uom.LogicalName, new Guid("5D15C954-A08E-DB11-934C-000E0C6AB271")); IOrganizationServiceFactory serviceFactory1 = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service1 = serviceFactory1.CreateOrganizationService(context.UserId); service1.Create(salesorderdetail); |
|
28.03.2012, 11:33 | #6 |
Участник
|
Может у Вас проверка на дубликаты включена?
А почему Вы пишете вот так? salesorderdetail["new_orda"] = new EntityReference("salesorder", id_1); salesorderdetail["salesorderid"] = id_1; У Вас 2 ссылки на заказ должны быть из одной строки? и разве не нужно указывать для salesorderdetail["salesorderid"] EntityReference? Последний раз редактировалось g.Naukovych; 28.03.2012 в 11:35. |
|
|
За это сообщение автора поблагодарили: mistah (1). |
28.03.2012, 11:44 | #7 |
Участник
|
g.Naukovych, да, спасибо, разобрался, все ок)
|
|
28.03.2012, 11:48 | #8 |
Участник
|
Так что собственно было? Проверка на дубликаты или неверный код?
|
|
28.03.2012, 11:56 | #9 |
Участник
|
код неправильный:
этой строкой - service.Create(salesorder); - тут я один раз создал сущность, а потом строкой Guid id_1 = service.Create(salesorder); создаю еще одну такую же и надо было так salesorderdetail["salesorderid"] = new EntityReference("salesorder", id_1), да |
|
28.03.2012, 12:34 | #10 |
Участник
|
Цитата:
т.е. для создания salesorderDetail нам необходимо id salesOrder, который появиться только после создания salesOrder. есть ли возможность как-либо связать эти две сущности, для передачи в контекст? |
|
28.03.2012, 15:19 | #11 |
Чайный пьяница
|
Цитата:
Сообщение от spirius
А существует ли возможность сделать создание этих двух сущностей одновременно? (напирмер с использованием CrmServiceContext.SaveChanges() )
т.е. для создания salesorderDetail нам необходимо id salesOrder, который появиться только после создания salesOrder. есть ли возможность как-либо связать эти две сущности, для передачи в контекст?
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
28.03.2012, 15:34 | #12 |
Участник
|
Цитата:
Сообщение от a33ik
Для создания чайлодовой сущности вам необходим идентивикатор парентовой. Я не пробовал, но может получиться следующий трюк (для 4.0 работал, для 2011 - не пробовал) - задайте идентификатор создаваемого SalesOrder и используйте тот же идентификатор при заполнении EntityReference salesorderid для SalesOrderDetail.
Последний раз редактировалось g.Naukovych; 28.03.2012 в 16:18. |
|
29.03.2012, 10:46 | #13 |
Участник
|
Цитата:
т.е. если сделать, например: context.AddObject(entity1); context.AddObject(entity2); context.SaveChanges(); будет ли вначале создана entity1, а затем создана entity2? p.s. AddRelatedObject() похоже может помочь. p.p.s. Спасибо за ответы=) несколько проблем решил=) |
|
29.03.2012, 11:01 | #14 |
Участник
|
а зачем это делать?
Создать сущность можно 1 строкой. В чем разница context.AddObject(entity1); или service.Create(entity1); |
|
29.03.2012, 11:35 | #15 |
Участник
|
Цитата:
создать SalesOrder только в том случае, если может быть создана его SalesOrderDetail. руками проверять ВСЕ поля SalesOrderDetail есть нехорошо, поэтому есть идея делать это через систему, и если система не может создать SalesOrderDetail - отлавливать эксепшн и соответственно ничего не создавать. правда в "несоздавании" SalesOrder сильно я не продвинулся, вот и ищу различные пути=) p.s. на сколько я понимаю, service.create создает сущность сразуже. если же мы используем context.addobject, то у нас еще есть возможность с ним работать, как с несозданным, до попадания его в систему. соответственно можно во время работы его из контекста выкинуть (неверное?) дабы он не создавался (если нам это стало ненужным). просто задача стоит еще и с точки зрения прав доступа - если у текущего пользователя нет, скажем, права удалять и изменять SalesOrder, то сделав service.create и попытавшись его изменить/удалить, должна вылететь системная ошибка, чтоли, о правах доступа. |
|
29.03.2012, 12:32 | #16 |
Участник
|
А как можно выполнить эту проверку?
SalesOrderDetail не создать без SalesOrder. Без него система всегда не сможет создать. Разве нет? |
|
30.03.2012, 10:25 | #17 |
Участник
|
Цитата:
проверять руками всю SalesOrderDetail неоптимально - любое изменение этой сущности, может сделать такую проверку неработающей. |
|
30.03.2012, 12:22 | #18 |
Участник
|
решение через проверку есть:
Guid newSalesOrderId = Guid.Empty; newSO.Id = Guid.NewGuid(); newSalesOrderId = newSO.Id; svcContext.AddObject(newSO); //создали ордер. добавили в контекст if(checkSalesOrderDetail(curSalesOrderDetail))//ручная проверка полей salesOrderDetail { //если все ОК, добавляем salesOrderDetail в контекст, связывая с ордером: svcContext.AddRelatedObject ( newSO, new Relationship("order_details"), curSalesOrderDetail ); } else { svcContext.DeleteObject(newSO);//иначе удаляем ордер из контекста } svcContext.SaveChanges(); |
|
|
|