Vamos ver aqui como se realiza um CRUD (Create, Retrieve, Update e Delete) no Microsoft Dynamics CRM 4.0, mas antes, vamos falar um pouco sobre a Plataforma Dynamics CRM 4.0. Como o nome do produto mesmo diz, o Dynamics CRM 4.0 é a última versão do Sistema de Relacionamento com o Cliente da Microsoft. Atualmente está disponível o Rollup 6 para correções de problemas na aplicação.

Totalmente desenvolvido em .NET C#, o CRM é muito mais do que um simples sistema de Relacionamento com o Cliente, ele também é uma plataforma altamente customizável, tanto a nível de tela (com alguns cliques é possível tanto criar entidades como campos) como a nível de customização de código. Como outros produtos Microsoft, o CRM possui uma série de Web services que permitem sua integração via código com outras aplicações e é nisto que se baseia este artigo.

Para começar vamos criar um novo projeto no Visual Studio 2008, um Console Application com o nome CRM – Contatos:

Console Application

Agora com nossa aplicação criada, vamos adicionar uma referência web ao CRM e para isto vamos ao Solution Explorer, no botão direito em cima do nome do projeto e clique em Add Service Reference > Advanced > Add Web Reference >. Na tela que se abriu no campo URL, vamos digitar o endereço do Web Service. O CRM disponibiliza dois webservices:

  • CrmService: interface de acesso aos dados contidos no CRM e é com ele que vamos trabalhar.
  • MetaDataService: interface para trabalhar com os metadados do CRM, ou seja, entidades, campos, regras, etc.

Normalmente, o endereço dos webservices do CRM é http:/// mscrmservices/2007/.

CRM

No Web reference name digite CRMSDK e clique em Add Reference:

CRM

Para começar, vamos colocar o namespace do CrmSdk na nossa aplicação e para isto basta digitarmos Using CrmSdk na parte superior do nosso código:

CrmSdk

A classe CrmService é a responsável pela comunicação da nossa aplicação com os dados internos do nosso CRM. Vamos instanciar a nossa classe para realizar a nossa conexão com o CRM da nossa empresa. Para isto precisamos informar o nosso login, URL do webservice e um detalhe a mais que não existia em versões anteriores: o CRMAuthenticationToken. Ele informa qual a forma de login da nossa aplicação e também a qual empresa estamos tentando conectar, já que agora o CRM 4.0 Enterprise pode disponibilizar várias empresas (também visto como instâncias nomeadas):

private CrmService crm;public CrmService CRM
{
     get
     {
                if (crm == null)
                {
                    crm = new CrmService();
                    //Autenticação passando Login e Senha
                    crm.Credentials = new System.Net.NetworkCredential
                     ("Administrator","qwer1234", "Dominio");
 
                    //URL do WebService
                    crm.Url = "http://endereco:5555/mscrmservices/2007/CrmService.asmx";
 
                    //Instanciar a classe CrmAuthenticationToken
                    CrmAuthenticationToken token = new CrmAuthenticationToken();
                    token.AuthenticationType = 0;//Autenticação via AD
                    /*Nome da Organização ao qual vamos conectar
                     * Em caso de dúvida, o nome fica em frente a url de acesso ao CRM
                     * Por exemplo: http://endereco:5555/ORGANIZACAO */
                    token.OrganizationName = "Organizacao";
                    crm.CrmAuthenticationTokenValue = token;
                    return crm;
                }
                else
                  return crm;
   }
}

Agora vamos criar um contanto na entidade Contato do nosso CRM. A forma de inserção é sempre a mesma, só muda o nome da entidade que vamos instanciar.

Como o CRMService nos proporciona um acesso altamente tipado as nossas entidades, é bastante simples trabalharmos com os dados que elas contêm ou conterão. Por exemplo, se queremos criar um contato basta instanciarmos a classe contato e preenchermos as devidas propriedades da classe, conforme o exemplo abaixo:

public void CriaContato()
{
            //Cria uma instancia da classe Contact
            contact contato = new contact();
            contato.firstname = "Olavo";
            contato.lastname = "Neto";
 
            this.CRM.Create(contato);
}

Após a execução do nosso novo método, se tudo ocorrer bem, poderemos ver dentro do CRM, na devida entidade, o nosso novo contato com os dados preenchidos:

CrmSdk

Capturando um dado no CRM

Bom, agora que já criamos um contato, vamos ver como capturá-lo. Como eu falei no tópico anterior, existem várias maneiras de se fazer algo no CRM, mas vou listar aqui o que considero as duas principais maneiras de capturar um dado dentro do CRM:

  1. Capturar uma coleção de dados dentro do CRM;
  2. Capturar um dado específico.

Capturar uma coleção de dados dentro do CRM

Retornar uma coleção de dados de dentro do CRM é bem parecido com executar uma QUERY dentro do SQL Server. De certa forma, o que vamos fazer é montar uma query através de um conjunto de classe e métodos do SDK.

public List<contact> CapturaContatos{
  List<contact> contatos = new List<contact>();

Como toda query em SQL, devemos iniciar informando às colunas que queremos obter na nossa consulta, em SQL utilizamos o SELECT. No CRM utilizamos o ColumnSet:

ColumnSet columns = new ColumnSet();
columns.Attributes = new string[] { "contactid", "fullname" };

Caso queria-se obter todas as colunas de uma única vez (SELECT * FROM) pode-se utilizar a classe AllColumns:

AllColumns columns = new AllColumns();

Vamos agora continuar nossa query com as restrições. Como no SQL, não é obrigatório o uso das restrições caso se deseje obter todos os dados das entidades.

A restrições do CRM se baseiam em duas classes, a primeira é a ConditionExpression aonde informamos o nome do campo que queremos pesquisar o operador da busca (Equal, Like, etc.) e o valor a ser pesquisado.

A segunda classe é a FilterExpression onde informaremos todas as condições já criadas e o operador entre elas (AND ou OR):

ConditionExpressionconditionNome =newConditionExpression();
conditionNome.AttributeName ="firstname";
conditionNome.Operator =ConditionOperator.Equal;
conditionNome.Values =newobject[] {"Olavo"};
FilterExpressionfilter =newFilterExpression();
filter.Conditions =newConditionExpression[] { conditionNome };

Agora, vamos ordenar nossa busca através da classe OrderExpression:

OrderExpressionorder =newOrderExpression();
order.AttributeName ="fullname";
order.OrderType =OrderType.Ascending;

Para finalizar, vamos juntar tudo no QueryExpression, classe principal da nossa busca, aonde informamos as colunas, os filtros, a entidade que iremos realizar a busca e os ordenadores.

QueryExpression query = new QueryExpression();
query.ColumnSet = columns;
query.Criteria = filter;
query.EntityName = EntityName.contact.ToString();
query.Orders = new OrderExpression[] { order };

Realizando a consulta através do método RetrieveMultiple que retorna uma BusinessEntityCollection (coleção de entidades):


BusinessEntityCollection bu = this.CRM.RetrieveMultiple(query);
foreach (BusinessEntity b in bu.BusinessEntities)
{
      contact contato = (contact)b;
      contatos.Add(contato);
      Console.Write("Anote este ID:" + contato.contactid.Value);
      Console.ReadLine();
}
 
return contatos;
}

Execute o método, copie o ID que apareceu, ele será importante para o próximo exemplo:

CrmSdk

Capturar um dado específico

Já vimos como realizar uma consulta completa no Dynamics CRM, agora vamos ver como criar uma busca direta pelo ID da entidade, para isto basta termos o Guid identificador da entidade e informamos as colunas que desejamos obter.

Para nosso exemplo, usei o AllColumns para retornar todas as colunas da entidade Contato.

A consulta é feita através do método Retrieve que retorna uma BusinessEntity:

public contact CapturaContato()
{
AllColumns columns = new AllColumns();
 return ((contact)this.CRM.Retrieve(EntityName.contact.ToString(),
  new Guid("e2850cd6-9cb6-dd11-b305-0014d11389c6"), columns));
 
}

Atualizando um Dado no CRM

Atualização é extremamente parecido com a inserção de dados. A única diferença é que se faz necessário informar a chave do registro que será modificado e em vez do método Create, utilizaremos o Update.

public void AtualizaContato()
        {
            contact contato = new contact();
            contato.contactid = new Key();
            contato.contactid.Value = new Guid("e2850cd6-9cb6-dd11-b305-0014d11389c6");
            contato.emailaddress1 = "luke_neto@hotmail.com";
            this.CRM.Update(contato);
        }

Veja o resultado dentro do CRM:

CrmSdk

Deletando um Dado no CRM

Deleção de dados é quase sempre o mais simples a ser feito, no CRM não é diferente. Para isto, basta chamarmos o método Delete e passar como parâmetro o nome da entidade que iremos deletar e a chave do registro:

public void DeletaContato()
 {
            this.CRM.Delete(EntityName.contact.ToString(),
                new Guid("e2850cd6-9cb6-dd11-b305-0014d11389c6"));
 }

Dicas

Algumas dicas que eu considero serem de ajuda para quem for trabalhar com o SDK do CRM:

  1. Também é possível realizar todos os procedimentos aqui mostrados, inclusive retornar os dados em XML, usando o método Fetch da classe CrmService.
  2. Quando for digitar o nome das colunas a serem capturadas no ColumnSet, nunca digite o nome delas ou coloque qualquer letra em MAIÚSCULO;
  3. A melhor maneira de verificar o que aconteceu de errado na sua aplicação é através do SoapExcepetion:
    catch(System.Web.Services.Protocols.SoapExceptionsoapEx)
    {
      throw newSystem.Web.Services.Protocols.SoapException
       (soapEx.Detail.InnerText,soapEx.Code);
    }
  4. Não é possível trabalhar com entidades associativas (entidades intermediárias de relacionamento N:N) diretamente, somente através do Fecth;
  5. Não se preocupe com os dados a serem retornados a nível de permissão, pois o CRM só traz os dados que aquele usuário logado tem permissão para ver;
  6. Existe um bug no CRM 4 no qual não é possível retornar as colunas StatusCode e StateCode de nenhuma entidade. Este problema foi resolvido no RollUp 2;
  7. Tente não usar o AllColumns, pois ele é tão prejudicial como o Select * From.