我需要将某些实体(帐户,潜在客户,联系人等)同步到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;
}
答案 0 :(得分:3)
如果您所追求的只是当前正在执行的插件的属性实体的名称,则EntityReference对象具有应包含该名称的Name属性。如果不是您,您可以使用id和逻辑名查询CRM,以获取您在引用实体上寻找的任何值。
如果您只是移动数据,为什么还要设置引用的名称呢?我从数据库表中删除了这些名称,只创建了一个查找相应实体名称的视图。这就是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;
对于链接的实体,您有三种选择。