Microsoft Dynamics CRM 2011将实体同步到外部数据库表中

时间:2013-03-14 17:45:24

标签: dynamics-crm-2011 dynamics-crm crm

我需要将某些实体(帐户,潜在客户,联系人等)同步到crm数据库之外但在同一服务器上的数据库表。我正在寻找一种支持的方式来做到这一点。这是我尝试过的,不起作用:

我首先在外部数据库中创建了与dbo.account(view)中的模式匹配的表。然后我写了post post,post update,post assign和post delete插件来创建,更新或删除外部表中的记录(使用ADO.Net)。我以最通用的方式编写了插件,以便可以对插件进行最少更改的任何实体注册(通过不对字段名称进行硬编码)。这样做,我遇到的问题是与其他表的外键的字段。例如。在dbo.account中,有PrimaryContactId和PrimaryContactIdName,PreferredSystemUserId和PreferredSystemUserIdName,ParentAccountId和ParentAccountIdName等字段。在插件的输入参数中,xxxxId字段在更新时可用,但不是'xxxxIdName'字段。因此,我无法按原样“同步”该表。

是否有解决方案使我的插件解决方案有效? 是否有更好的支持方式来拥有同步表? 提前谢谢,

PS:1。数据同步必须是实时的

PS:2。这是我获取执行更新的查询的函数

private static string PrepareUpdateQuery(ITracingService tracingService, IEnumerable<KeyValuePair<string, object>> attributeCollection, string entityName, string entityIdName)
    {

        var query = "Update MainDb.MSCRM." + entityName + " set ";
        foreach (KeyValuePair<string, object> keyValuePair in attributeCollection)
        {
            tracingService.Trace("Key: {0}", keyValuePair.Key);
            if (keyValuePair.Key != entityIdName && keyValuePair.Key != "modifiedonbehalfby")
            {
                query = query + keyValuePair.Key + " = ";
                if (keyValuePair.Value == null)
                    query = query + "null, ";
                else
                {
                    var typeOfValue = keyValuePair.Value.GetType().Name;
                    tracingService.Trace("typeOfValue: {0}", typeOfValue);
                    switch (typeOfValue)
                    {
                        case "EntityReference":
                            query = query + "'" + ((EntityReference)keyValuePair.Value).Id + "', ";
                            break;
                        case "OptionSetValue":
                            query = query + ((OptionSetValue)keyValuePair.Value).Value + ", ";
                            break;
                        case "BooleanManagedProperty":
                            query = query + (((BooleanManagedProperty)keyValuePair.Value).Value ? "1" : "0") + ", ";
                            break;
                        default:
                            query = query + "'" + keyValuePair.Value + "', ";
                            break;
                    }
                }
            }
        }
        return query;
    }

4 个答案:

答案 0 :(得分:3)

如果您所追求的只是当前正在执行的插件的属性实体的名称,则EntityReference对象具有应包含该名称的Name属性。如果不是您,您可以使用id和逻辑名查询CRM,以获取您在引用实体上寻找的任何值。

编辑1

如果您只是移动数据,为什么还要设置引用的名称呢?我从数据库表中删除了这些名称,只创建了一个查找相应实体名称的视图。这就是CRM正在做的事情。它还使您的其他数据库更加规范化。 IE浏览器。如果更新另一个实体引用的实体的名称,则必须搜索并更新所有这些名称...

答案 1 :(得分:1)

xxxIdName字段实际上只是视图的帮助器,您可以轻松找出它们的内容 应该包含。

例如,假设您拥有一个名为“bob bobson”的主要联系人的“某公司”帐户。 处理帐户实体时,primarycontactId将是一个guid,primarycontactIdName将是'bob bobson',accountIdName将是'某个公司'。

在插件中执行此操作的最简单方法是查找相关实体并从中获取值 - 有90%的时间它只是名称字段。

你还需要考虑一下,如果你在使用CRM模式时做的正确,也许最好只复制你需要的字段,并使用你自己的模式进行同步表。

更新:刚刚看到你的代码,你正在覆盖查询中包含的值,而不是将其设置回基本查询,所以你会在第二次通过foreach时得到奇怪的结果/错误

答案 2 :(得分:1)

如果您已经将相关实体名称放在主要实体表中,您可以像这样抓住它:

var entityEntityRef = (EntityReference)keyValuePair.Value;
var relatedEntity = service.Retrieve(entityRef.LogicalName, entityRef.Id, new ColumnSet(true));

现在relatedEntity可用的所有属性。你将主要寻找名称字段,但有些实体是不同的,比如使用我认为的全名字段的联系人。

答案 3 :(得分:0)

事实上,你可以为所有实体注册一个插件(当然,检查发送消息的那个插件是否在被处理的实体列表中)。

IEnumerable<String> supportees = new String[]{ "account", "contact" };
if(!supportees.Any(element
  => element == targetLogicalName))
    return;

对于链接的实体,您有三种选择。

  1. 跳过它们。不是完整的数据同步,但很容易实现。
  2. 仅存储guid。数据同步在整个范围内 - 有限但很容易。
  3. 获取所有链接数据。完整的信息,但开发的递归PIA。