Consultar objetos DTO a través de WCF con linq a backend sql

Estoy trabajando en un proyecto en el que necesitamos crear consultas complejas contra un servicio WCF.

El servicio usa linq to sql en el backend y proyecta consultas a objetos de transferencia de datos como este:


     dbContext.GetQueryable ()
                   .Donde (x => x.Id == formatId)
                     .Seleccione (x => FormatHelper.PopulateMSFormat (x))
                     .Listar();

Lo que quiero hacer es especificar una consulta en el lado del cliente, digamos que quiero consultar todos los formatos que tienen una propiedad determinada o un par de ellos. Algo en el estilo de esto:


      var assets = client.QueryForAssets (). Donde (x => (x.name == "Test" || x == "Arne") && x.doe == "john");

Soy consciente de que no puedo devolver IQueryable a través de WCF, pero que algo así se puede hacer con los servicios OData. El problema es que tengo que devolver los DTO y OData me permite enlazar fácilmente a L2S-datacontext que expone mi modelo de datos y no los DTO.

Entonces, ¿hay una buena manera de serializar una consulta contra el DTO que se propague de manera eficiente a la capa l2s?

Pensé en escribir mi propio lenguaje de consulta, pero descubrí que sería bastante difícil construir el árbol de expresión correcto como un predicado para l2s, ya que no hay una asignación desde el DTO a las clases de linq.

Con los servicios OData , no está obligado a devolver entidades de base de datos directamente. Simplemente puede devolver cualquier DTO en formato consultable. Luego, con la ayuda del método Select() de LINQ, puede simplemente convertir cualquier entidad de base de datos a DTO justo antes de atender la consulta:

 public class DataModel { public DataModel() { using (var dbContext = new DatabaseContext()) { Employees = from e in dbContext.Employee select new EmployeeDto { ID = e.EmployeeID, DepartmentID = e.DepartmentID, AddressID = e.AddressID, FirstName = e.FirstName, LastName = e.LastName, StreetNumber = e.Address.StreetNumber, StreetName = e.Address.StreetName }; } } /// Returns the list of employees. public IQueryable Employees { get; private set; } } 

Ahora puede configurar fácilmente esto como un servicio OData como este:

 public class EmployeeDataService : DataService 

Para detalles completos de implementación, vea este excelente artículo sobre el tema. Los servicios de OData son en realidad muy, muy poderosos una vez que los manejas.

Creo que puede devolver los DTO mediante el uso de servicios OData.

Eche un vistazo a http://www.codeproject.com/Articles/135490/Advanced-using-OData-in-NET-WCF-Data-Services . Particularmente la sección ‘Exponiendo una transformación de su base de datos’. Puede aplanar sus objetos de entidad en un DTO y hacer que el cliente ejecute consultas contra este modelo de DTO.

¿Es eso algo que estás buscando?

Si tienes entidades complicadas durante mucho tiempo, entonces crear una proyección a mano es una pesadilla. Automapper no funciona porque LINQ no puede usarlo junto con IQueryable.

Esta es la solución perfecta: Stop using AutoMapper in your Data Access Code

Generará una proyección ‘mágicamente’ para usted y le permitirá ejecutar una consulta oData basada en su clase DTO (objeto de transferencia de datos).

  [Queryable] public IQueryable GetDatabaseProductDTO(ODataQueryOptions options) { // _db.DatabaseProducts is an EF table // DatabaseProductDTO is my DTO object var projectedDTOs = _db.DatabaseProducts.Project().To(); var settings = new ODataQuerySettings(); var results = (IQueryable) options.ApplyTo(projectedDTOs, settings); return results.ToArray().AsQueryable(); } 

Corro esto con

 /odata/DatabaseProductDTO?$filter=FreeShipping eq true 

Nota: este artículo es de hace un par de años y es posible que para ahora AutoMapper tenga una funcionalidad como esta incorporada. Simplemente no tengo tiempo. Lo compruebo ahora mismo. La inspiración para el artículo mencionado anteriormente se basó en este artículo del autor de AutoMapper, por lo que es posible que ahora se incluya alguna versión mejorada. El concepto general parece genial y esta versión funciona bien para mí.