Dynamics 365 – Relacionar Entidade Virtual (Virtual Entity) com Entidade Nativa/Cutomizada


Olá pessoal,

Bom, hoje vou demonstrar como criar relacionamentos entre uma Entidade Nativa/Customizada e Entidades Virtuais!

Na figura acima, um novo relacionamento (1:N) foi criado entre a entidade Contato (contact) e a entidade virtual External Activity (new_externalentity).

Para aqueles que ainda não viram meus posts anteriores, acesse aqui:

Dynamics 365 – Entidades Virtuais
Dynamics 365 – Dicas para utilizar Entidades Virtuais

Indo ao assunto deste post…

API

O primeiro passo é ter/criar a API que será consumida pela entidade virtual. Neste exemplo, para utilizar o provider nativo (OData V4), precisamos que nossa API implemente este protocolo.

Existem vários exemplos na internet, utilizei este aqui:

https://www.aspsnippets.com/Articles/Simple-WCF-JSON-Rest-Service-Tutorial-with-example-in-C-and-VBNet.aspx

Assim, vamos para o Visual Studio, primeiro um screenshot do Solution Explorer para ajudar a se localizar:

Abaixo minha Model (ExternalActivity.cs):

using System;
using System.ComponentModel.DataAnnotations;

namespace DemoODataV4.Models
{
    public class ExternalActivity
    {
        [Key]
        public Guid ExternalActivityId { get; set; }

        public int ExternalActivityKey { get; set; }

        public Guid ContactId { get; set; }

        public string Subject{ get; set; }

        public string Details { get; set; }

        public string From { get; set; }

        public string To { get; set; }

    }
}

Linha 9: Veja que a chave primária ExternalActivityId é um GUID e tem a anotação “[Key]“.

Linha 13: Atualmente a única maneira de relacionar uma entidade à outra é através do uso de uma atributo do tipo GUID

Agora minha Controller (ExternalActivitiesController.cs):

using DemoODataV4.Datasource;
using System.Linq;
using System.Web.Http;
using System.Web.OData;

namespace DemoODataV4.Controllers
{
    public class ExternalActivitiesController : ODataController
    {
        [EnableQuery]
        public IHttpActionResult Get()
        {
            return Ok(DemoDataSource.Instance.ExternalActivities.AsQueryable());
        }
    }
}

Como eu não tinha uma fonte de dados, decidi criar uma camada de dados falsa/mock, assim, consigo manipular os registros que serão criados. Estou criando 1.000 registros falsos e também uso um gerador randomico de palavras.

Vamos ao código do meu data source (DemoDataSource.cs), vou detalhar melhor logo após ele:

using System;
using DemoODataV4.Models;
using System.Collections.Generic;
using System.Linq;

namespace DemoODataV4.Datasource
{
    public class DemoDataSource
    {
        private static DemoDataSource instance = null;
        public static DemoDataSource Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new DemoDataSource();
                }
                return instance;
            }
        }

        public List<ExternalActivity> ExternalActivities { get; set; }

        private DemoDataSource()
        {
            this.Reset();
            this.Initialize();
        }
        public void Reset()
        {
            ExternalActivities = new List<ExternalActivity>();
        }
        public void Initialize()
        {
            for (int i = 0; i < 1000; i++)
            {
                Guid contactId = Guid.NewGuid();
                Guid externalActivityId = Guid.NewGuid();

                if (i < 50)
                {
                   contactId = new Guid("C4BA7D70-347B-E811-A961-000D3AE05F14");
                }

                ExternalActivities.AddRange(new List<ExternalActivity>
                {
                    new ExternalActivity()
                    {
                        ExternalActivityId = externalActivityId,
                        ExternalActivityKey = i,
                        ContactId = contactId,
                        From = RandomString(10),
                        To = RandomString(10),
                        Subject= RandomString(20),
                        Details = RandomString(100),
                    }
                });
            }
        }

        static Random random = new Random();

        public static string RandomString(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
        }
    }
}

Na parte de código que está destacada, para os 50 primeiros, estou atribuindo um ID (C4BA7D70-347B-E811-A961-000D3AE05F14) de um contato (contact) que existe em meu Dynamics 365. Assim quando acessarmos este registro, apenas 50 registros serão exibidos.

Neste post, não irei me aprofundar como recuperar o ID de um contato no Dynamics através de uma outra chave de negócios, como poderia ser usando o atributo “ExternalActivityKey“.

Por último, a classe de inicialização (WebApiConfig.cs) dentro do App_Start:

using DemoODataV4.Models;
using Microsoft.OData.Edm;
using System.Web.Http;
using System.Web.OData.Batch;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;

namespace DemoODataV4
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapODataServiceRoute("odata", null, GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
            config.EnsureInitialized();

            config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); //new line
        }
        private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.Namespace = "DemoODataV4";
            builder.ContainerName = "DefaultContainer";
            builder.EntitySet<ExternalActivity>("ExternalActivities");
            var edmModel = builder.GetEdmModel();
            return edmModel;
        }
    }
}

Pronto a API está pronta! Vamos ao Dynamic 365!

Dynamics 365

Temos duas etapas para realizar no Dynamics, a primeira é criar o data source de nossa entidade virtual:

Escolha como data provider o OData V4 e depois informe os detalhes de sua API.

Vale lembrar aqui que se por exemplo sua API possui o seguinte endereço http://XXX/DemoODataV4Service/ExternalActivities, devemos apenas informar a http://XXX/DemoODataV4Service/, o nome do serviço será informado no momento da criação da entidade virtual!

Como o data source criado, vamos a entidade virtual:

Selecione o checkbox “Virtual Entity” e selecione o data source que criamos na etapa anterior.

Não se esqueça de informar o External Name e External Collection Name, eles devem ser os que foram utilizados na criação da API.

Já no atributo primário e faça as devidas mudanças antes de criar a entidade virtual:

Agora é a vez de informar o External Name da chave primária (new_ExternalActivityId) da entidade virtual:

Devemos criar o relacionamento (1:N) entre Contatos e External Activity:

Veja acima que o External Name (ContactId) é o mesmo nome utilizado na Model da API.

Crie os demais atributos implementados na Model, sempre lembrando de criar atributos com o mesmo tipo de dado e como External Name o mesmo nome utilizado na propriedade da Model.

Depois adicione todos os atributos no formulário e visualizações da entidade virtual para que seja possível ve-los quando acessarmos o contato. Publique e atualize o seu navegador!

Pronto! Sua entidade virtual está configurada para acessar dados externos. Abra o mesmo contato que utilizamos o seu GUID de forma fixa na API. Depois navegue até as entidades relacionadas, clique em External Acitivities:

Ao abrirmos os registros (clicando duas vezes), vemos o formulário em modo apenas leitura com os atributos já preenchidos:

Bom, isso é tudo! Espero ter ajudado!

[]’s,

Tiago

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.