Umas das novidades mais legais do Microsoft Dynamics CRM 4.0 é a possibilidade de criar relacionamento N:N (Many to Many) entre as entidades, este tipo de relacionamento me possibilita por exemplo dizer que um contato contém vários contatos e que vários contatos participam de vários contratos diferentes.
Claro que, para quem conhece, não existe relacionamento N:N dentro do banco de dados, ou é N:1 ou 1:N, então como isto é possível....a resposta é tão simples, ao solicitarmos a criação de um relacionamento do tipo Many to Many entre duas entidades, o CRM, de forma implícita, cria uma tabela intermediária no banco de dados que contém apenas quatro atributos, sendo dois deles as chaves primárias das entidades relacionadas:
Abstraindo todas as colunas das entidades laterais, a figura acima mostra a tabela de referencia para o relacionamento N:N.
Legal, vamos para o divertido, como trabalhar com está novidade via SDK...primeiro vem a noticia chata, as tabelas intermediarias não são visualizadas como entidades então não podemos trabalhar com o Retrieve nem com o RetrieveMultiple para poder Capturar os dados, o mesmo vale para a gravação de dados, não podemos usar os métodos comuns para este procedimento, porem não é difícil realizar tais operações.
Criando Dados em entidades N:N
O processo de gravação é bem simples, para isto contamos com a classe AssociateEntitiesRequest que junto com a classe Moniker serão os responsáveis por gravar os dados no nosso BD:
- Para iniciar, deve-se adicionar a Referencia ao endereço http://ENDEREÇO_crm/mscrmservices/2007/CrmService.asmx sob o nome de CrmSdk.
- No topo da classe, vamos instanciar as bibliotecas do CRM através do comando using CrmSdk;
Vamos criar uma classe void responsável apenas por salvar os Contatos que fazem relacionamento com os contratos:
public void SalvaContato_Contrato()
{
//Instância uma nova conexão ao CRM
CrmService service = new CrmService();
service.PreAuthenticate = true;
//Instância o Token de autenticação
CrmAuthenticationToken Token = new CrmAuthenticationToken();
Token.AuthenticationType = 0;//0 = Autenticação por AD
Token.OrganizationName = "Olavo";
//Nome da Organização ao qual vamos nos conectar
service.CrmAuthenticationTokenValue = Token;
//Informa usuário que está conectando
service.Credentials = new System.Net.NetworkCredential
("Olavo", "----------------", "CRM4");
//Inicia o Request
AssociateEntitiesRequest associateRequest = new AssociateEntitiesRequest();
//Moniker 1 será responsável pelos dados da entidade Contact
associateRequest.Moniker1 = new Moniker();
associateRequest.Moniker1.Id = new Guid
("cd06d480-40b9-de11-a3af-00155d013108");
associateRequest.Moniker1.Name = EntityName.contact.ToString();
//Moniker 2 será responsavel pelos dados da entidade Contract
associateRequest.Moniker2 = new Moniker();
associateRequest.Moniker2.Id = new Guid
("EC1864D0-40B9-DE11-A3AF-00155D013108");
associateRequest.Moniker2.Name = EntityName.contract.ToString();
//Informa o nome do relacionamento
associateRequest.RelationshipName = "servicecontractcontacts_association";
AssociateEntitiesResponse response =
(AssociateEntitiesResponse)service.Execute(associateRequest);
Capturando Dados da tabela de interseção
Capturar os dados contidos nas tabelas de interseção (intermediarias) é um processo simples, porém bem diferente do usual Retrieve e do RetrieveMultiple. Por se tratar de tabelas de interseção e não de entidades propriamente ditas, o CRM não consegue realizar consultas diretas dentro dela, tanto que se você tentar pesquisar o nome da tabela através do Enum EntityName, verá que não consta o nome da tabela de interseção.
A partir de agora, para realizarmos este tipo de consulta, teremos de usar o método Fetch da classe CrmService trabalha com consulta em XML e que retorna o resultado também em XML.
O código para realizar a consulta fica mais ou menos assim:
public Guid RetornaUsuario_Contrato()
{
//Instância uma nova conexão ao CRM
CrmService service = new CrmService();
service.PreAuthenticate = true;
//Instância o Token de autenticação
CrmAuthenticationToken Token = new CrmAuthenticationToken();
Token.AuthenticationType = 0;//0 = Autenticação por AD
Token.OrganizationName = "Olavo";
//Nome da Organização ao qual vamos nos conectar
service.CrmAuthenticationTokenValue = Token;
//Informa usuário que está conectando
service.Credentials = new System.Net.NetworkCredential
("Olavo", "----------------", "CRM4");
//Monta o XML de consulta
//Entity name = <INFORMA Nome interseção de tabela da o>
//Caso se queria utilizar mais de um Condition,
//deve-se acrescentar no filter type = 'and'>
string Consulta =
@"<FETCH mapping="logical">
<ENTITY name="servicecontractcontacts">
<ALL-ATTRIBUTES />
<FILTER>
<CONDITION operator="eq" attribute="contractid"
value='EC1864D0-40B9-DE11-A3AF-00155D013108' />
</FILTER>
</ENTITY>
</FETCH>";
//Captura resultado
string Resultado = service.Fetch(Consulta);
//Trabalhando com o XML retornado
System.Xml.XmlDocument Document = new System.Xml.XmlDocument();
Document.LoadXml(Resultado);
System.Xml.XmlNodeList XmlNodes =
Document.SelectNodes("resultset/result/contactid");
if (XmlNodes.Count > 0)
return new Guid(XmlNodes[0].InnerText);
return Guid.Empty; }
É isto pessoal. Nada de muito complicado, porem extremamente útil quando se tem entidades se relacionamento de N:N no Microsoft Dynamics CRM 4.0