quinta-feira, 23 de abril de 2015

CRM Tips - Import Solution - RibbonCustomization

Por um acaso, ao tentar importar uma solução no CRM, já se deparou com o seguinte erro:

There should only be at most one instance of RibbonCustomization per solution per entity. Current entity: [entityName]. Current solution: [guid]

Pois bem, muito provavelmente o metadados de Ribbons do seu CRM está, digamos, corrompido! São vários os motivos para que isto possa ter ocorrido, como por exemplo, em uma migração de versão.

Como se corrige isto, então? Atue no metadados de Ribbons, eliminando as duplicidades.

A Procedure abaixo faz justamente isto, para todas as entidades do banco do CRM.


declare @tables table (id int identity, name nvarchar(100))

declare @count int, @currentTable nvarchar(100), @sql nvarchar(max)

declare @RibbonCustomizationId uniqueidentifier, 
  @RibbonCustomizationUniqueId uniqueidentifier,
  @Entity nvarchar(100),
  @SolutionId uniqueidentifier,
  @SupportingSolutionId uniqueidentifier,
  @ComponentState int,
  @OverwriteTime datetime,
  @OrganizationId uniqueidentifier,
  @PublishedOn datetime,
  @IsManaged bit

-- BUSCA TODAS AS TABELAS DO CRM
insert into @tables (name)
select name
from sysobjects
where type = 'v'
order by name

-- LOOP NAS TABELAS
select @count = count(*) from @tables
while (@count > 0)
begin
 select @currentTable = name from @tables where id = @count

 -- CRIA UMA TEMP TABLE PARA GUARDAR OS RIBBONS AGRUPADOS POR [SolutionId]
 declare @Unique_RibbonCustomization table (
  RibbonCustomizationId uniqueidentifier, 
  RibbonCustomizationUniqueId uniqueidentifier,
  Entity nvarchar(100),
  SolutionId uniqueidentifier,
  SupportingSolutionId uniqueidentifier,
  ComponentState int,
  OverwriteTime datetime,
  OrganizationId uniqueidentifier,
  PublishedOn datetime,
  IsManaged bit)

 insert into @Unique_RibbonCustomization
  select RibbonCustomizationId, RibbonCustomizationUniqueId, Entity, SolutionId, SupportingSolutionId, ComponentState, OverwriteTime, OrganizationId, PublishedOn, IsManaged
  from (
     select *,
      row_number() over (partition by SolutionId order by SolutionId) as row_number
     from RibbonCustomization
     where entity = @currentTable
     ) as r
  where row_number = 1

 -- GUARDA OS IDS (RibbonCustomizationId) QUE POSSUEM DUPLICIDADE DE RIBBON
 declare @Diff_RibbonCustomization table (RibbonCustomizationId uniqueidentifier)
 insert into @Diff_RibbonCustomization
  select RibbonCustomizationId
  from RibbonCustomization
  where entity = @currentTable and
     RibbonCustomizationId not in (select RibbonCustomizationId from @Unique_RibbonCustomization)

 if (exists(select * from @Diff_RibbonCustomization))
 begin

  print 'Correcting EntityRibbon for: ' + @currentTable + '...'

  -- EXCLUIR OS RIBBONS DUPLICADOS PARA A ENTIDADE DO LOOP
  delete from RibbonCustomization 
  where Entity = @currentTable and
     RibbonCustomizationId in (select RibbonCustomizationId from @Diff_RibbonCustomization)

  -- EXCLUI AS DEPENDÊNCIAS (SolutionComponentBase, dependencybase e DependencyNodeBase)
   delete from SolutionComponentBase where ObjectId in (select RibbonCustomizationId from @Diff_RibbonCustomization)

  delete db from dependencybase db 
      inner join dependencynodebase dnb 
     on db.dependentcomponentnodeid = dnb.dependencynodeid or
     db.RequiredComponentNodeId = dnb.dependencynodeid
  where dnb.ObjectId in (select RibbonCustomizationId from @Diff_RibbonCustomization)
 
  delete from DependencyNodeBase where ObjectId in (select RibbonCustomizationId from @Diff_RibbonCustomization)
 end

 select @count = @count - 1, @currentTable = null
end

print 'Done.'


Após rodar a proc você conseguirá importar sua solução sem problemas - espero! :)

[]s

terça-feira, 21 de abril de 2015

CRM Tips - Managed to UnManaged Solution

Se por um acaso - ou falta de conhecimento - você criou uma solução Gerenciada no CRM por engano e precisa convertê-la para não gerenciada, segue um Script que faz este trabalho por você, já que até o momento a MS não disponibilizou uma opção para isto na ferramenta.

Importante notar que esta ação é sim suportada porque inclusive é ensinada no TechEd (aos 43:08 min do vídeo referenciado no final deste artigo). Eu somente fiz algumas alterações na procedure para atender melhor nosso cenário.

No script abaixo substitua a palavra [SolutionName] pelo nome de sua solução gerenciada que deseja converter.


declare @solutionId uniqueidentifier, @systemSolutionId uniqueidentifier
select @solutionId = solutionid from solutionbase where uniquename = 'SolutionName'
select @systemSolutionId = solutionid from solutionbase where uniquename = 'active'

update publisherbase 
set isreadonly = 0 
where publisherid in
(
select publisherid from solutionbase where solutionid = @solutionId
)

declare @tables table (id int identity, name nvarchar(100), ismanaged bit, issolution bit)
declare @count int, @currentTable nvarchar(100), @currentM bit, @currentS bit, @sql nvarchar(max)

insert into @tables (name, ismanaged, issolution)
select name, 1, 0
from sysobjects
where id in
(
select id from syscolumns where name in ('ismanaged')
)
and type = 'u'
order by name

insert into @tables (name, ismanaged, issolution)
select name, 0, 1
from sysobjects
where id in
(
select id from syscolumns where name in ('solutionid')
)
and type = 'u'
and name not in ('solutioncomponentbase')
order by name

select @count = count(*) from @tables

while (@count > 0)
begin
 select @currentTable = name, @currentM = ismanaged, @currentS = issolution from @tables where id = @count

 if (@currentM = 1)
 begin
  select @sql = 'update ' + @currentTable + ' set isManaged = 0 where SolutionId = N''' + cast(@solutionId as nvarchar(100)) + ''''
  exec (@sql)
 end

 print 'updated IsManaged to 0 on: ' + @currentTable

 select @count = @count - 1, @currentTable = null
end


Basicamente este código busca todas as tabelas que possuem os atributos [ismanaged] e [solutionid] para poder transformar os componentes da solução em não gerenciáveis e redirecionar as dependências para a solução interna do CRM chamada [Active].

Ref: Advanced Bag of Tips & Tricks for Microsoft Dynamics CRM 2011 Developers

[]s