plugins - Fetchxml del lado del servidor devuelve resultados diferentes
dynamics-crm-2011 (1)
Uno de nuestros procedimientos les permite a los usuarios insertar en forma masiva registros relacionados seleccionando una vista y luego presionando un botón de cinta. El formulario se guarda, se establece un indicador y un complemento hace su trabajo.
Estamos utilizando una sub-malla con un selector de vista para permitir a los usuarios elegir o crear sus propias vistas sobre la marcha. Una vez que se selecciona una vista, se muestra el número de resultados (proporcionado es lte 5k).
Cuando un complemento ejecuta el mismo lado del servidor fetchxml (Recuperación de userquery o savedquery, luego Retrieve + FetchExpression), los resultados cambian. Obtenemos no solo una cantidad diferente de registros, sino que también algunos registros son diferentes.
Concluimos que el problema tiene que ver con los husos horarios. Algunos filtros incluyen operadores "on-or-after" junto con valores de fecha. Ejemplo:
<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>
El complemento se ejecutó como administrador. Cambiar el usuario del complemento no tiene ningún efecto, como si la zona horaria del usuario actual no se tuviera en cuenta al extraer registros del CRM con FetchExpression.
¿Cómo puedo asegurarme de que una expresión fetchxml devuelva los mismos resultados del lado del cliente y del servidor?
Probablemente relacionado: MSDN thread .
Gracias por tu tiempo.
Editar: siguiendo la sugerencia de Daryl, ejecuté un rastreo SQL. Los resultados son desconcertantes. Las fechas se compensan correctamente para las consultas del lado del cliente (se ejecutan desde CRM, es decir, Búsqueda avanzada); esto significa que el fetchxml se traduce correctamente utilizando la configuración de la zona horaria del usuario. Esto no ocurre para la misma consulta, en el lado del servidor; el SQL de salida contiene los filtros de fecha "tal cual", sin compensación de zona horaria. Supuse que se producía la misma traducción sin importar el origen del contexto de ejecución de la consulta.
Editar 2: una marca en una región oculta de código (mi último recurso de depuración) impedía que el complemento creara una instancia del servicio en el contexto del usuario en ejecución. Todo funciona bien ahora. Gracias a todos por su tiempo y su ayuda, es muy apreciado.
Cuando trabaje con fechas, recuerde siempre convertirlas a utc ya que así es como CRM las almacena en la base de datos.
El hallazgo CRM Advanced nativo buscará cualquiera que sea el huso horario del usuario actual, y lo convertirá a cualquier hora que ingresen en el hallazgo avanzado a UTC antes de realizar una consulta SQL. El control de tu complemento necesitará hacer lo mismo. Estos son los pasos que deberá realizar antes de poner los criterios en Expresión de búsqueda / Expresión de consulta / Expresión de consulta.
- Obtenga el UserSetting.TimeZoneCode del usuario a través de su SystemUserId.
- Busque TimeZoneDefinition.StandardName para TimeZoneCode en el paso 1
- Llame a TimeZoneInfo.FindSystemTimeZoneById () pasando el nombre estándar del paso 2 (puede combinar los pasos 1 y 2 en una sola consulta, pero prefiero guardar en caché los resultados del paso tres usando la entrada del paso 1 para una ligera mejora en el rendimiento). . use un diccionario con TimeZoneCode como clave y TimeZoneInfo como valor)
- Utilice esta función para obtener el valor de UTC para el tiempo que va a utilizar en su consulta de complemento:
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;
}