Consultas con LINQ en Microsoft Dynamics CRM 2011

6 Jun 2020 webmaster

Al utilizar las clases de programación en tiempo de compilación (EarlyBound) se puede generar una clase derivada de la clase OrganizationServiceContext si se especifica el nombre de la clase utilizando el parámetro servicecontextname cuando se utiliza la herramienta de generación de código (CrmSvcUtil.exe ). El uso de esta clase permite hacer referencia a un conjunto de entidades IQueryable utilizando el esquema patrón <nombre + Set>, por ejemplo AccountSet para hacer referencia al conjunto de registros de la entidad de la cuenta.

Si hemos generado la clase Entities.cs desde el explorador del CRM dentro Microsoft Visual Studio, comando (Generate Wrapper) ésta no nos vale para realizar consultas LINQ porque necesitamos un parámetro adicional que es el serviceContextName que nos servirá para que la clase sea consultada via LINQ, lo que nos obliga a volver a generarla nuevamente desde la linea de comandos utilizando la sintaxis a continuación:

CrmSvcUtil.exe /url:http://<serverName>/<organizationName>/XRMServices/2011/Organization.svc>/out:<outputFilename>.cs /username:<username> /password:<password> /domain:<domainName>/namespace:<outputNamespace> /serviceContextName:<serviceContextName>

Según nuestra configuracion on Premise vamos a realizar la regeneración de la Clase Entity por esta vía situados en la carpeta donde tenemos instalado nuestro SDK.

En la ejecución del programa la primera vez nos dio error por no poder grabar el archivo especificado en el parámetro /out:Entities.cs y lo cambiamos a /out:C:\Temp\Entities.cs

Con esta nueva entidad generada, sustituimos la antigua que teniamos incorporada a nuestro proyecto y comenzamos a utilizar consultas LINQ a nuestro CRM. A continuación mostramos dos ejemplos de consultas EarlyBound y LateBound realizadas con LINQ que reflejan la poca diferencia entre ellas:

Ejemplo EarlyBound

En nuestro código tenemos la variable service que contiene los parámetros de conexion a nuestro CRM de tipo OrganizationService y queremos obtener el ID de un registro en la Entidad Paises cuyo nombre del Pais es España. Crearíamos una función que nos devuelva ese valor utilizando LINQ por el metodo EarlyBound como se muestra a continuación:

//Llamada al metodo de la Clase ApplicationSettings para obtener la conexion al CRM
static OrganizationService service = ApplicationSettings.GetCrmService();
//Llamamos a la función que devolverá el valor
Guid paisId = SearchEarlyLINQPais("España", service);
static Guid SearchEarlyLINQPais(string nombre_pais, OrganizationService service)
{
  Guid paisId = Guid.Empty;
  ServiceContext svcContext = new ServiceContext(service);
  var query = from n in svcContext.new_paisesSet
		  where (string)n.new_name==nombre_pais
		  select new
		  {
			id = n.new_paisesId
		  };
	  foreach (var reg in query)
	  {
		paisId=(Guid)reg.id ;
	  }
  return paisId;
}

Observaciones:
1. Llamamos a la Entidad new_paises como una propiedad de svcContext con el esquema patrón <nombre + Set>
2. Las Entidades están disponibles en la clase Entities.cs y se comprueban en tiempo de complilación.

Ejemplo LateBound

En nuestro código tenemos la variable service que contiene los parámetros de conexion a nuestro CRM de tipo OrganizationService y queremos obtener el ID de un registro en la Entidad Paises cuyo nombre del Pais es España. Crearíamos una función que nos devuelva ese valor utilizando LINQ por el metodo LateBound como se muestra a continuación:

//Llamada al metodo de la Clase ApplicationSettings para obtener la conexion al CRM
static OrganizationService service = ApplicationSettings.GetCrmService();
//Llamanos a la función que devlverá el valor
Guid paisId = SearchEarlyLINQPais("España", service);
static Guid SearchLateLINQPais(string nombre_pais, OrganizationService service)
{
  Guid paisId = Guid.Empty;
  ServiceContext svcContext = new ServiceContext(service);
  var query = from n in svcContext.CreateQuery("new_paises")
		where (string)n["new_name"] == nombre_pais
		select new
		{
		  id = n.Attributes["new_paisesid"]
		};
	  foreach (var reg in query)
	  {
		paisId = (Guid)reg.id;
	  }

  return paisId;

}

Observaciones:
1. Llamamos a la Entidad new_paises utilizando el metodo CreateQuery de svcContext  en formato string
2. Las Entidades se comprobarán en tiempo de ejecución.
3. El Id del pais se obtiene mediate la propiedad Attributes[<nombre del campo>] del registro que se obtiene.

Restrinciones de LINQ

LINQ OperadorLimitaciones

join - Representa un inner join. No se puede implementar outer joins.

from - Solo un from por consulta.

where - El lado izquierdo de la cláusula debe ser un nombre de atributo y el lado derecho de la cláusula debe ser un valor. No se puede ajustar el lado izquierdo para una constante. Ninguno de los lados de la cláusula pueden ser constantes. Soporta funciones stringContains, StartsWith, EndsWith, y Equals.

groupBy- No soportado. FetchXML soporta funciones de agrupamiento que no están habilitadas en el proveedor de LINQ.

orderBy - Solo soporta ordenamiento por entity attributes, como Contact.FullName.

select - Soporta tipos anonimos, constructores e inicializadores.

last - No soportado.

aggregated - No soportado.

skip and take - Soportado durante el uso de la la paginación del lado del servidor (server-side paging). El valor del skip debe ser mayor o igual que el valor del take.

 

Redirect to Facebook Page