19.03.2012, 23:56 | #1 |
Участник
|
Post Update Event “Generic Sql Error” crm 2011
Всем доброй ночи
Такая проблема Если я пытаюсь сделать Retrieve либо RetrieveMultiple в Post Update например сущности контакт. Падает со следующей ошибкой: X++: Message: Generic SQL error. Stack Trace: Server stack trace: at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Microsoft.Xrm.Sdk.IOrganizationService.Retrieve(String entityName, Guid id, ColumnSet columnSet) at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.RetrieveCore(String entityName, Guid id, ColumnSet columnSet) at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.Retrieve(String entityName, Guid id, ColumnSet columnSet) 1. Использования сервиса из сборок MS. 2. Если ретрив направлен на туже сущность в плагине которой код находится. (если плагин бежит на изменения контакта и ретрив тоже на контакт, тогда он падает) Если я использую сервис из контекста ретривы срабатывают без проблем. Тот же самый ретрив прекрасно срабатывает на Pre update/Pre Create/Post Create Короче галиматья какая-та. Ошибка в трейсе такая: Взяв из ошибки запрос и запустив его в SQL Management Studio срабатывает без проблем X++: Exception when executing query: select "contact0".FullName as "fullname" , "contact0".ContactId as "contactid" , "contact0".OwningBusinessUnit as "owningbusinessunit" , "contact0".OwningUser as "owninguser" , "contact0".OwnerId as "ownerid" , "contact0".OwnerIdType as "owneridtype" from Contact as "contact0" where ("contact0".ContactId = 'ef08d04f-a417-e111-bbcc-000c2977cd58') Exception: System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() at Microsoft.Crm.CrmDbConnection.InternalExecuteWithRetry[TResult](Func`1 ExecuteMethod, IDbCommand command) at Microsoft.Crm.CrmDbConnection.InternalExecuteReader(IDbCommand command, Boolean capturePerfTrace) at Microsoft.Crm.CrmDbConnection.ExecuteReader(IDbCommand command, Boolean impersonate, Boolean capturePerfTrace) at Microsoft.Crm.BusinessEntities.BusinessProcessObject.ExecuteQuery(CrmDbConnection dbConnection, IDbCommand command, ISqlExecutionContext context) [2012-03-19 21:40:03.071] Process: w3wp |Organization:e5d0c6a5-4014-4eb1-b466-46876080e569 |Thread: 14 |Category: Platform.Sql |User: f350993d-7114-e111-9bcc-000c2977cd58 |Level: Error | BusinessProcessObject.DoRetrieve >Exception when executing query: select "contact0".FullName as "fullname" , "contact0".ContactId as "contactid" , "contact0".OwningBusinessUnit as "owningbusinessunit" , "contact0".OwningUser as "owninguser" , "contact0".OwnerId as "ownerid" , "contact0".OwnerIdType as "owneridtype" from Contact as "contact0" where ("contact0".ContactId = 'ef08d04f-a417-e111-bbcc-000c2977cd58') Exception: System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() at Microsoft.Crm.CrmDbConnection.InternalExecuteWithRetry[TResult](Func`1 ExecuteMethod, IDbCommand command) at Microsoft.Crm.CrmDbConnection.InternalExecuteReader(IDbCommand command, Boolean capturePerfTrace) at Microsoft.Crm.CrmDbConnection.ExecuteReader(IDbCommand command, Boolean impersonate, Boolean capturePerfTrace) at Microsoft.Crm.BusinessEntities.BusinessProcessObject.ExecuteQuery(CrmDbConnection dbConnection, IDbCommand command, ISqlExecutionContext context) at Microsoft.Crm.BusinessEntities.BusinessProcessObject.DoRetrieve(BusinessEntityMoniker moniker, BusinessEntity entity, EntityExpression entityExpression, ExecutionContext context, Int32 languageCode, DatabaseQueryTarget queryTarget) Такая же ситуация с плагином который написан под 4, если он бежит из под crm 2011. Буду рад всем предложениям по поводу решения этой проблемы. Заранее Благодарен Константин
__________________
Читайте SDK!!! |
|
20.03.2012, 00:46 | #2 |
Участник
|
Собственно я не очень понял Ваш вопрос.
Если я использую сервис из контекста ретривы срабатывают без проблем. Значит нужно его использовать. Теперь по поводу почему это происходит. И происходит именно так. И Происходит именно так в CRM 2011 В CRM 2011 теперь плагины выполняются в транзакции. В CRM есть след. шаги плагинов 10 PreOperation 20 PreValidation 30 40 PostOperation 50 PostOperation (deprecated) Шаги 20 30 40 находятся в транзакции В CRM 4 мы могли вешать плагин на 10 PreOperation и на 50 PostOperation В CRM 2011 на 10 PreOperation, 20 PreValidation и 40(СОРОК) PostOperation То есть любой плагин выполняется в транзакции. Тепер что получается? Когда данные в транзакции и еще не сохранены в БД полностью Вы пытаетесь её считать. Вот у Вас и ошибка. Я это проверял при попытке считать из БД данные напрямую. Также проверял, что это работает если использовать веб-сервис из контекста плагина. Еще можно попробовать повесить это все на асинхронную операцию. таким образом, когда данные будут сохранены и их можно будет считать, асинхронный плагин отвиснет и считает. С получением данных из БД это работало. Напишите если это помогло. В подтверждении своих слов нашёл у Вас следующее The timeout period elapsed prior to completion of the operation То есть представте, что Вы пишете в таблицу ContactBase и ContactExtantionBase. В этот самый момент данные еще не сохранены. и Вы тут же пытаетесь считать данные. При чем из другой транзакции. Естественно другая транзакция ждёт, когда Вы данные отпустите, а Вы их не отпускаете и ждете, когда другая транзакция их получит. Это явный DeadLock. В результате TimeOut. Вот теперь это точно. Последний раз редактировалось g.Naukovych; 20.03.2012 в 00:53. |
|
|
За это сообщение автора поблагодарили: Konstantin Katsovich (2). |
20.03.2012, 10:12 | #3 |
Участник
|
Цитата:
Цитата:
Сообщение от g.Naukovych
То есть любой плагин выполняется в транзакции.
Тепер что получается? Когда данные в транзакции и еще не сохранены в БД полностью Вы пытаетесь её считать. Вот у Вас и ошибка. Я это проверял при попытке считать из БД данные напрямую. Также проверял, что это работает если использовать веб-сервис из контекста плагина. Если использовать веб-сервис из контекста плагина у меня ошибка не вываливается. Остается ещё очень много вопросов, которые все вместе не дают полную картину. Рочему в Post Create (40) этого не происходит? Теперь перейдем в плагину написаному для четверки который падает по той же причине. 50 stage уже не находится в транзакции почему тогда он тоже падает? Он поддерживается? Или получается код который написан под 4 не обязательно будет бежать на том же stage в 2011. (галиматья какая-та) P. S. Предыдущий программист который писал этот плагин использовал References на веб сервис для удобства работы с сущностями. теперь если переделывать его плагин на сервис из контектста придется переписывать весь код. P. S. Теперь нельзя делать ретривы в Post Update при использовании сборок либо References на веб сервис.
__________________
Читайте SDK!!! |
|
20.03.2012, 10:23 | #4 |
Участник
|
Я видимо неправильно выразился.
Если вызывать веб-сервис из контекста, то работать должно. Это работает и у меня и у Вас. Цитата:
Теперь перейдем в плагину написаному для четверки который падает по той же причине.
50 stage уже не находится в транзакции почему тогда он тоже падает? Он поддерживается? Тут еще тонкий момент. Вы наверного обращаетесь к crmService. Это способ работы с CRM4 В CRM 2011 рекомендуется работать с OrganizationService Цитата:
P. S. Предыдущий программист который писал этот плагин использовал References на веб сервис для удобства работы с сущностями. теперь если переделывать его плагин на сервис из контектста придется переписывать весь код.
Цитата:
P. S. Теперь нельзя делать ретривы в Post Update при использовании сборок либо References на веб сервис.
|
|
20.03.2012, 11:28 | #5 |
Участник
|
Он не запрешен
Если Вы делаете перенос проекта с 4 на 2011 и у вас там есть плагины именно на него (50) и нужно их вешать. Конечно же нельзя плагин неписаный под 2011 повешать на этот евент. Plugin Registration вам этого не даст Цитата:
это существует для crm 2011, а не для crm 4. (Плагин написан под crm 4)
__________________
Читайте SDK!!! |
|
20.03.2012, 11:44 | #6 |
Участник
|
В любом случае плагин не работает на шаге 50, даже если он на него мигрировал.
Можно сделать еще ё вариант, не уверен попойдёт ли он Вам. Плагин повесить на шаг 10. КОгда еще нет транзакции. На основе PreImage и таргет сформировать PostImage. Потом вызвать Вашу операцию и заменить там значение, которое получилось у той записи, что вы изменили на значение из PostImage. Или еще 1 вариант переведите плагин в асинхронных режим. То есть когда Вы будете обращаться к списку записей у Вас уже будет не DeadLock, а просто Lock. Вы проиграете по времени в вычислениях, данные не будут приходить сразу же, но при этом они все равно изменятся и Вам не придётся переписывать плагин. |
|
20.03.2012, 11:57 | #7 |
Участник
|
Цитата:
Можно даже его менять и он снова работает. P. S. А за варианты спасибо
__________________
Читайте SDK!!! |
|
20.03.2012, 12:00 | #8 |
Участник
|
а Как Вы транзакцию побороли?
А если в него зайти и шаг посмотреть там 50 написано? |
|
20.03.2012, 12:10 | #9 |
Участник
|
Я видимо переделаю плагин на DynamicEntity в том же самом stage и буду использовать сервис контекста.
Не хочу изобретать велосипед Да 50
__________________
Читайте SDK!!! |
|
20.03.2012, 12:13 | #10 |
Участник
|
В CRM 2011 вместо DynamicEntity есть просто Entity. С ними немного удобнее работать
|
|
21.03.2012, 02:43 | #11 |
Moderator
|
Ваша проблема связанна именно с транзакционностью плагинов CRM 2011. В SDK по этому поводу даже есть несколько строк:
Access to the Organization Service To access the Microsoft Dynamics CRM organization service, it is required that plug-in code create an instance of the service through the ServiceProvider.GetService method. C# Copy Code // Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); The platform provides the correct Web service URLs and network credentials for you when you use this method. Instantiating your own Web service proxy is not supported as it will create deadlock and authentication issues.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
|
За это сообщение автора поблагодарили: Konstantin Katsovich (1). |
21.03.2012, 10:28 | #12 |
Участник
|
Цитата:
Сообщение от Артем Enot Грунин
Ваша проблема связанна именно с транзакционностью плагинов CRM 2011. В SDK по этому поводу даже есть несколько строк:
Access to the Organization Service To access the Microsoft Dynamics CRM organization service, it is required that plug-in code create an instance of the service through the ServiceProvider.GetService method. C# Copy Code // Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); The platform provides the correct Web service URLs and network credentials for you when you use this method. Instantiating your own Web service proxy is not supported as it will create deadlock and authentication issues. P. S. странно я поставил 5
__________________
Читайте SDK!!! Последний раз редактировалось Konstantin Katsovich; 21.03.2012 в 10:33. Причина: добавление "P.S." |
|
|
|