使用linq到sql后端通过WCF查询DTO对象

我正在开发一个项目,我们需要针对WCF服务创建复杂的查询。

该服务在后端使用linq to sql并将查询投影到数据传输对象,如下所示:


     dbContext.GetQueryable()
                   .Where(x => x.Id == formatId)
                     .Select(x => FormatHelper.PopulateMSFormat(x))
                     .ToList();

我想要做的是在客户端指定一个查询,假设我想查询具有某个属性或其中几个属性的所有格式。 这个风格的东西:


      var assets = client.QueryForAssets()。Where(x =>(x.name ==“Test”|| x ==“Arne”)&& x.doe ==“john”);

我知道我无法通过WCF返回IQueryable,但是可以使用OData服务完成类似的事情。 问题是我必须返回DTO和OData让我很容易绑定到L2S-datacontext,它暴露我的数据模型而不是DTO。

那么是否有一种很好的方法可以将针对DTO的查询序列化,从而有效地传播到l2s层?

我想过编写自己的查询语言,但我发现将正确的表达式树构建为l2s的谓词是很困难的,因为没有从DTO到linq类的映射。

使用OData服务,您不必直接返回数据库实体。 您只需以可查询的格式返回任何DTO即可。 然后在LINQ的Select()方法的帮助下,您可以在提供查询之前简单地将任何数据库实体转换为DTO

 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; } } 

您现在可以轻松将其设置为OData服务,如下所示:

 public class EmployeeDataService : DataService 

有关完整的实现细节, 请参阅此主题的优秀文章。 一旦你掌握了它们,OData服务实际上非常强大。

我相信您可以使用OData服务返回DTO。

请查看http://www.codeproject.com/Articles/135490/Advanced-using-OData-in-NET-WCF Compone-Services 。 特别是“公开数据库的转换”部分。 您可以将实体对象展平为DTO,并让客户端针对此DTO模型运行查询。

那是你要找的东西吗?

如果你有很长的复杂实体,那么手工制作投影就是一场噩梦。 Automapper不起作用,因为LINQ不能与IQueryable一起使用它。

这是完美的解决方案: Stop using AutoMapper in your Data Access Code

它将为您“神奇地”生成投影,并使您能够基于DTO(数据传输对象)类运行oData查询。

  [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(); } 

我用它来运行

 /odata/DatabaseProductDTO?$filter=FreeShipping eq true 

注意:这篇文章来自几年前,现在AutoMapper可能具有内置的function。我只是没有时间自己检查这个。 上面引用的文章的灵感来自于AutoMapper本身的作者的这篇文章 – 所以现在可能包含它的一些改进版本。 一般概念看起来很棒,这个版本对我来说效果很好。