2

我们的一个程序允许用户通过选择一个视图然后点击功能区按钮来批量插入相关记录。保存表单,设置标志,然后插件完成其工作。

我们使用带有视图选择器的子网格来让用户动态选择或创建自己的视图。选择视图后,将显示结果数(提供 lte 5k)。

当插件运行相同的 fetchxml 服务器端(检索用户查询或保存查询,然后检索 + FetchExpression)时,结果会发生变化。我们不仅得到不同数量的记录,而且一些记录也不同。

我们得出结论,这个问题与时区有关。一些过滤器包括“on-or-after”运算符以及日期值。例子:

<filter type="and">
  <condition attribute="modifiedon" operator="on-or-after" value="2011-01-01" />
  <condition attribute="modifiedon" operator="on-or-before" value="2011-12-31" />
</filter>

该插件以管理员身份运行。更改插件用户没有效果 - 就好像在使用 FetchExpression 从 CRM 中提取记录时不考虑当前用户时区一样。

如何确保 fetchxml 表达式在客户端和服务器端返回相同的结果?

可能相关:MSDN 线程

谢谢你的时间。

编辑:按照 Daryl 的建议,我运行了 SQL 跟踪。结果令人费解。客户端查询的日期正确偏移(从 CRM 运行,即高级查找) - 这意味着使用用户的时区设置正确翻译了 fetchxml。对于服务器端的相同查询,这不会发生;输出 SQL 包含“原样”的日期过滤器,没有时区偏移。我假设无论查询执行上下文的来源如何,都会发生相同的翻译。

编辑 2:隐藏代码区域中的标志(我最后的调试手段)阻止插件在运行用户的上下文中实例化服务。现在一切运行良好。感谢大家的时间和帮助,非常感谢。

4

1 回答 1

6

处理日期时,请始终记住转换为 UTC,因为 CRM 就是这样将它们存储在数据库中的。

本地 CRM 高级查找将查看当前用户的时区,并在执行 SQL 查询之前将他们输入高级查找的任何时间转换为 UTC。您的插件控件将需要做同样的事情。这些是在将条件放入 Fetch Xml/Linq 表达式/查询表达式之前需要执行的步骤。

  1. 通过他们的 SystemUserId 获取用户的 UserSetting.TimeZoneCode。
  2. 从步骤 1 中查找 TimeZoneCode 的 TimeZoneDefinition.StandardName
  3. 调用 TimeZoneInfo.FindSystemTimeZoneById() 从第 2 步传入标准名称(您可以将第 1 步和第 2 步组合到一个查询中,但我更喜欢使用第 1 步的输入缓存第 3 步的结果以稍微提高性能。即. 使用以 TimeZoneCode 作为键, TimeZoneInfo 作为值的字典)
  4. 使用此函数获取您将在插件查询中使用的时间的 UTC 值:

public static DateTime ConvertTimeToUTC(DateTime time, TimeZoneInfo timeZone)
{
    if (time.Kind != DateTimeKind.Unspecified)
    {
        // If the DateTime is created with a specific time zone(ie DateTime.Now), getting the offset will
        // blow chow if it isn't the correct time zone:
        // The UTC Offset of the local dateTime parameter does not match the offset argument.
        //Parameter name: offset

        // This quick check will recreate the serverLocal time as unspecified

        time = new DateTime(
            time.Year,
            time.Month,
            time.Day,
            time.Hour,
            time.Minute,
            time.Second,
            time.Millisecond);

    }
    var offest = new DateTimeOffset(time, timeZone.GetUtcOffset(time));
    return offest.UtcDateTime;
}
于 2012-07-06T18:09:16.037 回答