Home

Consultas con LINQ en Microsoft Dynamics CRM 2011

webmaster's picture

En Microsoft Dynamics CRM 2011, se puede utilizar .NET Language-Integrated Query ( LINQ) para escribir consultas. Para ello hay que utilizar la clase OrganizationServiceContext o una clase derivada creado por la herramienta CrmSvcUtil escribir consultas LINQ que acceden al extremo SOAP del servicio web principal (Organization.svc) . La clase OrganizationServiceContext contiene un proveedor de consultas LINQ subyacente que se traduce consultas LINQ de Microsoft Visual C # o Microsoft Visual Basic. NET sintaxis en la API de consulta utilizado por Microsoft Dynamics CRM.

 

 

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 Operador Limitaciones

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.

 

Fuente: 

Centro Práctico de LEMURSOLUTION & Knowledge Base de Microsoft Dynamics

Contacto: 
webmaster