Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

这篇具有很好参考价值的文章主要介绍了Dynamics 365: 详解虚实体(Virtual Entity) 从0到1。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

从Dynamics 365 for Customer Engagement 9.0开始,虚实体通过在Dynamics 365 Customer Engagement中无缝地将数据表示为实体,实现了外部系统中的数据集成。它无需数据复制,通常也无需自定义编码。

虚实体有如下的限制,但除了下面的这些限制外,它和其它的那些自定义实体没有区别:

  • 数据是只读的。虚实体特性不支持在 Dynamics 365中 CE所做的更改在推回到外部系统
  • 只支持实体的组织级权限。不支持字段级安全
  • 对于外部数据,需要抽象建模为D365的支持的那些字段,就比如说你想获取外部系统中一条记录的姓名,性别,年龄字段,那么在虚实体中,你需要创建与姓名,性别和年龄字段相符的字段类型,比如text, number, optionset, date, image, 和lookup类型
  • 外部数据的记录必须有一个GUID格式的主键与虚实体中的主键相关联
  • 无法使用计算字段,如果需要计算,需要在外部系统完成或者在data provider中进行处理。
  • 无法筛选某一列的值或者进行对其进行排序
  • 不支持Audit History
  • 不能为queue启用虚实体
  • 虚实体不支持BPF
  • 虚实体一旦创建就不能更改为普通实体

1. 创建插件并注册

这个插件将会实现Retrieve和Retrieve Multiple,示例代码中是连接到另外一个组织的D365中,获取Account实体里的记录并显示出来.

将这些hardcode写到你的插件中并不是一个很好的方法,我这样做主要是为了让你可以更容易看到它是如何工作的,你在编写自己的代码的时候需要将这些配置信息妥善处理一下

对于如何下面代码中的这些配置信息在Azure中的什么地方能够找到,大家可以参考下面的这篇博客

Dynamics 365: 如何从Azure中获取连接到D365 Online所需要的认证信息_Stone-hdj的博客-CSDN博客https://blog.csdn.net/djstone/article/details/124927079?spm=1001.2014.3001.5502

Retrieve:

using Microsoft.Xrm.Sdk;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;

namespace VirtualEntityODataProvider
{
    public class Retrieve : IPlugin
    {
        //set these values for your D365 instance, user credentials and Azure AD clientid/token endpoint
        string crmorg = "https://orgeXXXX.crm5.dynamics.com";
        string clientid = "b004872a-XXXX-XXXX-XXXX-4a21868c04db";
        string username = "applicationuser@XXXX.onmicrosoft.com";
        string userpassword = "XXXX";
        string tokenendpoint = "https://login.microsoftonline.com/594a2057-XXXX-XXXX-XXXX-0bc293dfb025/oauth2/token";
        string clientsecret = "mTQ8Q~2bc84~fMK5Z0qc123456XXXdaG";

        //relative path to web api endpoint
        string crmwebapi = "/api/data/v9.2";

        string crmwebapipath = "/accounts({Id})?$select=name,accountid";

        public void Execute(IServiceProvider serviceProvider)
        {
            //basic plugin set-up stuff
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory servicefactory = XXXX(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting Tracing!");

            try
            {
                EntityReference target = (EntityReference)context.InputParameters["Target"];

                //build the authorization request for Azure AD
                var reqstring = "client_id=" + clientid;
                reqstring += "&client_secret=" + clientsecret;
                reqstring += "&resource=" + Uri.EscapeUriString(crmorg);
                reqstring += "&username=" + Uri.EscapeUriString(username);
                reqstring += "&password=" + Uri.EscapeUriString(userpassword);
                reqstring += "&grant_type=password";

                //make the Azure AD authentication request
                WebRequest req = WebRequest.Create(tokenendpoint);
                req.ContentType = "application/x-www-form-urlencoded";
                req.Method = "POST";
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(reqstring);
                req.ContentLength = bytes.Length;
                System.IO.Stream os = req.GetRequestStream();
                os.Write(bytes, 0, bytes.Length);
                os.Close();

                tracingService.Trace($"Request token completed");
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                StreamReader tokenreader = new StreamReader(resp.GetResponseStream());
                string responseBody = tokenreader.ReadToEnd();
                tokenreader.Close();

                tracingService.Trace($"Parsing token response");
                //deserialize the Azure AD token response and get the access token to supply with the web api query
                var tokenresponse = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseBody);
                var token = tokenresponse["access_token"];
                tracingService.Trace($"token:{token}");
                //make the web api query
                WebRequest crmreq = WebRequest.Create(crmorg + crmwebapi + crmwebapipath.Replace("{Id}", target.Id.ToString()));
                crmreq.Headers = new WebHeaderCollection();

                //use the access token from earlier as the authorization header bearer value
                crmreq.Headers.Add("Authorization", "Bearer " + token);
                crmreq.Headers.Add("OData-MaxVersion", "4.0");
                crmreq.Headers.Add("OData-Version", "4.0");
                crmreq.Headers.Add("Prefer", "odata.maxpagesize=500");
                crmreq.Headers.Add("Prefer", "odata.include-annotations=OData.Community.Display.V1.FormattedValue");
                crmreq.ContentType = "application/json; charset=utf-8";
                crmreq.Method = "GET";

                HttpWebResponse crmresp = (HttpWebResponse)crmreq.GetResponse();
                StreamReader crmreader = new StreamReader(crmresp.GetResponseStream());
                string crmresponseBody = crmreader.ReadToEnd();
                crmreader.Close();
                tracingService.Trace($"Retrieve completed");
                //deserialize the response
                var crmresponseobj = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(crmresponseBody);
                

                tracingService.Trace($"Retrieve result completed, crmresponseobj = {crmresponseobj}");
                Entity verow = new Entity("cr8e0_otheraccount");
                verow["cr8e0_otheraccountid"] = (Guid)crmresponseobj["accountid"];
                verow["cr8e0_name"] = (string)crmresponseobj["name"];

                //return a result
                context.OutputParameters["BusinessEntity"] = verow;
            }
            catch (Exception e)
            {
                tracingService.Trace($"{e.Message} {e.StackTrace}");
                if (e.InnerException != null)
                    tracingService.Trace($"{e.InnerException.Message} {e.InnerException.StackTrace}");

                throw new InvalidPluginExecutionException(e.Message);
            }
        }
    }
}

Retrieve Multiple:

using Microsoft.Xrm.Sdk;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;

namespace VirtualEntityODataProvider
{
    public class RetrieveMultiple : IPlugin
    {
        //set these values for your D365 instance, user credentials and Azure AD clientid/token endpoint
        string crmorg = "https://orgeXXXX.crm5.dynamics.com";
        string clientid = "b004872a-XXXX-XXXX-XXXX-4a21868c04db";
        string username = "applicationuser@XXXX.onmicrosoft.com";
        string userpassword = "XXXX";
        string tokenendpoint = "https://login.microsoftonline.com/594a2057-XXXX-XXXX-XXXX-0bc293dfb025/oauth2/token";
        string clientsecret = "mTQ8Q~2bc84~fMK5Z0qc123456XXXdaG";

        //relative path to web api endpoint
        string crmwebapi = "/api/data/v9.2";

        //web api query to execute - in this case all accounts that start with "A"
        string crmwebapipath = "/accounts?$select=name,accountid&$filter=startswith(name,'A')";

        public void Execute(IServiceProvider serviceProvider)
        {
            
            //basic plugin set-up stuff
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting Tracing!");

            try
            {
                EntityCollection results = new EntityCollection();

                //build the authorization request for Azure AD
                var reqstring = "client_id=" + clientid;
                reqstring += "&client_secret=" + clientsecret;
                reqstring += "&resource=" + Uri.EscapeUriString(crmorg);
                reqstring += "&username=" + Uri.EscapeUriString(username);
                reqstring += "&password=" + Uri.EscapeUriString(userpassword);
                reqstring += "&grant_type=password";

                //make the Azure AD authentication request
                WebRequest req = WebRequest.Create(tokenendpoint);
                req.ContentType = "application/x-www-form-urlencoded";
                req.Method = "POST";
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(reqstring);
                req.ContentLength = bytes.Length;
                System.IO.Stream os = req.GetRequestStream();
                os.Write(bytes, 0, bytes.Length);
                os.Close();

                tracingService.Trace($"Request token completed");
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                StreamReader tokenreader = new StreamReader(resp.GetResponseStream());
                string responseBody = tokenreader.ReadToEnd();
                tokenreader.Close();

                tracingService.Trace($"Parsing token response");
                //deserialize the Azure AD token response and get the access token to supply with the web api query
                var tokenresponse = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseBody);
                var token = tokenresponse["access_token"];
                tracingService.Trace($"token:{token}");
                //make the web api query
                WebRequest crmreq = WebRequest.Create(crmorg + crmwebapi + crmwebapipath);
                crmreq.Headers = new WebHeaderCollection();

                //use the access token from earlier as the authorization header bearer value
                crmreq.Headers.Add("Authorization", "Bearer " + token);
                crmreq.Headers.Add("OData-MaxVersion", "4.0");
                crmreq.Headers.Add("OData-Version", "4.0");
                crmreq.Headers.Add("Prefer", "odata.maxpagesize=500");
                crmreq.Headers.Add("Prefer", "odata.include-annotations=OData.Community.Display.V1.FormattedValue");
                crmreq.ContentType = "application/json; charset=utf-8";
                crmreq.Method = "GET";

                HttpWebResponse crmresp = (HttpWebResponse)crmreq.GetResponse();
                StreamReader crmreader = new StreamReader(crmresp.GetResponseStream());
                string crmresponseBody = crmreader.ReadToEnd();
                crmreader.Close();
                tracingService.Trace($"Retrieve multiple completed");
                //deserialize the response
                var crmresponseobj = JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(crmresponseBody);

                //loop through the response values
                foreach (var row in crmresponseobj["value"].Children())
                {
                    //create a new virtual entity of type lpa_demove
                    Entity verow = new Entity("cr8e0_otheraccount");
                    verow["cr8e0_otheraccountid"] = (Guid)row["accountid"];
                    verow["cr8e0_name"] = (string)row["name"];

                    //add it to the collection
                    results.Entities.Add(verow);
                }

                tracingService.Trace($"Retrieve results completed, there are {results.Entities.Count} items!");
                //return the results
                context.OutputParameters["BusinessEntityCollection"] = results;
            }
            catch (Exception e)
            {
                tracingService.Trace($"{e.Message} {e.StackTrace}");
                if (e.InnerException != null)
                    tracingService.Trace($"{e.InnerException.Message} {e.InnerException.StackTrace}");

                throw new InvalidPluginExecutionException(e.Message);
            }
        }
    }
}

需要注意上面的代码中用到了Newtonsoft这个第三方的Nuget包,所以我们需要使用ILMerge或者Costura.Fody来打包成一个dll.

注册插件(不需要注册step,后续创建Data Provider的时候会自动添加MainOperation这个step)

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

2. 注册Data Provider

Plugin Registeration Tool: Register -> Register New Data Provider

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

Solution: 这里我们选择新建一个solution, 它里面会放我们下面填的Data Source Entity(虚实体)

Data Source Entity:选择新建一个data source

Assembly: 选择我们刚刚注册的插件

RetrieveRetrieve Multiple:也是选择我们我们刚刚创建的

注册完成后我们会看到,第一步我们创建的插件里的就会被自动填充步骤

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 并且我们发现里面的步骤都是不可编辑的

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 3. 系统内部新建Data Source

Setting -> Administration -> Virtual Entity Data Sources

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

选择我们上面第二步创建的Data Provider

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 填写Name并保存Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 4. 创建虚实体

实体里需要把Virtual Entity选中,Data Source选择我们刚刚创建的数据源

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 Note:这一步里的字段需要和上面代码里的是对应上的,如下图

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

5. 效果

我们使用高级查找去测试一下,高级查找会调用Retrieve Multiple

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

 因为我们代码中做了过滤,只提取A开头的AccountDynamics 365: 详解虚实体(Virtual Entity) 从0到1

 当我们点击其中一条记录来打开,它会调用Retrieve

Dynamics 365: 详解虚实体(Virtual Entity) 从0到1

参考链接:

Get started with virtual entities (Developer Guide for Dynamics 365 Customer Engagement) | Microsoft Docshttps://docs.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/virtual-entities/get-started-ve?view=op-9-1#limitations-of-virtual-entities使用自定义数据源配置虚拟实体 - 微软MVP(15-18)罗勇 - 博客园 (cnblogs.com)https://www.cnblogs.com/luoyong0201/p/Dynamics_365_Develop_Virtual_Entity_with_Custom_Data_Provider.htmlUsing Dynamics 365 virtual entities to show data from an external organization (alexanderdevelopment.net)https://alexanderdevelopment.net/post/2018/05/28/using-dynamics-365-virtual-entities-to-show-data-from-an-external-organization/文章来源地址https://www.toymoban.com/news/detail-464907.html

到了这里,关于Dynamics 365: 详解虚实体(Virtual Entity) 从0到1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 对Dynamics365的理解

    ​简单地讲,Dynamics 365就是将CRM和ERP整合于统一的云服务中,并将功能细化为多个应用,客户可以按需采购,同时以共享数据模型以及统一的开发平台为基础,整合微软在生产力、智能分析、大数据、IoT等领域的能力,为企业实现数字化转型不断赋予能力 Dynamics 365可以说相当

    2024年02月01日
    浏览(55)
  • Dynamics 365 CRM 性能优化

    1. 应用程序开发时使用多线程开发。 2. 允许系统创建GUID。 3. 使用早绑定。 4. 插件优化。 5. 更新数据最小颗粒,谨防引起限制级联的操作。 6. 避免通过共享海量的数据做权限控制。 7. 不要修改CRM的一些限制。 8. 避免太广泛 无意义的模糊搜索 参考文档:微软文档

    2024年02月07日
    浏览(45)
  • Microsoft Dynamics 365 CE 扩展定制 - 7. 安全

    在本章中,我们将介绍以下内容: 构建累积安全角色 配置业务单元层次结构 基于分层位置配置访问 配置和分配字段级安全 组建团队并共享 设置访问团队 对静止数据进行加密以满足FIPS 140-2标准 管理Dynamics 365在线SQLTDE加密密钥 Dynamics 365是一个强大的平台,具有超过10年的良

    2024年02月05日
    浏览(39)
  • Dynamics 365 设置Postman environment For WebAPI

         在官网看到这么一篇\\\"Set up a Postman environment\\\",不用在Azure AD中注册application就可以在postman中构建WebAPI,对于开发者来说确实能帮助我们更快的上手开发,但国内用的是21V,所以本篇就来记录下验证后在21V中的可用性。       首先根据博文中的描述,我先找了个galobal的环

    2024年02月11日
    浏览(46)
  • 自定义Dynamics 365实施和发布业务解决方案 - 6. Azure集成

    在本章中,我们将讨论可用于实现快速和可扩展解决方案的Azure集成。我们将重点关注在Dynamics365实现中有用的三种类型的Azure技术。它们是Azure WebJobs、函数和逻辑应用程序。Azure WebJobs非常适合在后台运行的批处理。由于我们在本章中讨论的是Azure技术,我们还将快速了解一些

    2024年02月09日
    浏览(45)
  • Dynamics 365 Finance and Operations 创建你的第一个项目框架

    第一章:浅谈Dynamics CRM开发转Dynamics AX开发的感受与差异 第二章:Dynamics 365 Finance and Operations 虚拟机安装及使用 第三章:Dynamics 365 Finance and Operations 创建你的第一个项目(Visual Studio) 本文为大家介绍如何在Visual Studio中创建Model和Solution。并且让你了解Model和solution的基本概念

    2024年02月06日
    浏览(53)
  • 微软D365 入门文章汇总以及各项认证介绍(持续跟新.....) 自定义Dynamics 365实施和发布业务解决方案 (9章)

    希望入门D365的同学们,需要具备的知识点,涉及C#,WebApi,前端知识,Power Platform等知识,以及Azure的知识点等,需要有了解。 实施Microsoft Dynamics 365 CE-1. Dynamics 365 CE简介,提供了有关Dynamics 365客户参与度的基本详细信息_Martin-Mei的博客-CSDN博客 实施Microsoft Dynamics 365 CE-2. 实施

    2024年02月09日
    浏览(51)
  • Dynamics 365应用程序开发 - 6. 使用Microsoft Flow自动化业务流程

    在上一章中,我们了解了如何使用Microsoft PowerApps轻松创建自定义商业应用程序。在本章中,我们将了解Microsoft Flow,它可以定义为一种基于云的服务,使用户能够构建跨多个应用程序和服务自动化不同任务和流程的工作流。 在本章中,我们将介绍以下几点: 什么是Microsoft

    2024年02月09日
    浏览(40)
  • 自定义Dynamics 365实施和发布业务解决方案 - 4. 自动化业务流程

    本章的主要重点是研究拟议应用程序的关键业务流程的自动化。每个组织每天都有自己独特的业务操作,这些操作是业务的关键部分。有些自动化的业务流程不需要用户交互,有些流程需要用户交互。此外,在某些业务流程中,某些用户操作完成,然后触发自动化流程来完成

    2024年02月09日
    浏览(46)
  • Microsoft Dynamics 365:导入License到服务层,通过Business Central Administration Shell

    本文主要是Microsoft Dynamics 365的License导入的图解干货,不多赘述,直接上图: 第一步:准备好的License文件放在你喜欢的目录下 第二步:到开始程序里找到并打开 Business Central Administration Shell 3.第三步:执行导入命令 Import-NAVServerLicense -ServerInstance Starlite_0217 -LicenseFile \\\"D:Starl

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包