2

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

我首先在外部数据库中创建了与 dbo.account (视图)中的模式匹配的表。然后我写了post create、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

4 回答 4

3

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

编辑 1

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

于 2013-03-14T17:57:52.420 回答
1

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

例如,假设您有一个名为“some company”的帐户,其主要联系人为“bob bobson”。在处理帐户实体时,primarycontactId 将是一个 guid,primarycontactIdName 将是“bob bobson”,accountIdName 将是“some company”。

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

但是,您还需要考虑,如果您在使用 CRM 架构时做正确的事情,也许最好只复制您需要的字段并为同步表使用您自己的架构。

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

于 2013-03-14T18:14:19.113 回答
1

如果您一心想将相关实体名称放在主实体表中,您总是可以像这样抓取它:

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

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

于 2013-03-14T18:51:14.713 回答
0

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

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

至于链接实体,您有三个选择。

  1. 跳过它们。不是完整的数据同步,但易于实施。
  2. 仅存储指南。数据同步是实例范围的 - 有限但比较容易。
  3. 获取所有链接数据。完整的信息,但要开发递归 PIA。
于 2013-03-14T22:34:56.480 回答