Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用linq到sql后端通过WCF查询DTO对象_C#_Sql_Wcf_Linq_Dto - Fatal编程技术网

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

C# 使用linq到sql后端通过WCF查询DTO对象,c#,sql,wcf,linq,dto,C#,Sql,Wcf,Linq,Dto,我正在做一个项目,我们需要创建复杂的查询 WCF服务 该服务在后端使用linq to sql,并将查询投影到数据传输对象,如下所示: dbContext.GetQueryable() .Where(x => x.Id == formatId) .Select(x => FormatHelper.PopulateMSFormat(x)) .ToList(); dbContext.Ge

我正在做一个项目,我们需要创建复杂的查询 WCF服务

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

dbContext.GetQueryable() .Where(x => x.Id == formatId) .Select(x => FormatHelper.PopulateMSFormat(x)) .ToList(); 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"); var assets=client.QueryForAssets()。其中(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
                  };
    }
  }

  /// <summary>Returns the list of employees.</summary>
  public IQueryable<EmployeeDto> Employees { get; private set; }
}
公共类数据模型
{
公共数据模型()
{
使用(var dbContext=newdatabasecontext())
{
Employees=来自dbContext.Employee中的e
选择新员工待办事项
{
ID=e.EmployeeID,
部门ID=e.部门ID,
AddressID=e.AddressID,
FirstName=e.FirstName,
LastName=e.LastName,
StreetNumber=e.Address.StreetNumber,
StreetName=e.Address.StreetName
};
}
}
///返回员工列表。
公共IQueryable雇员{get;private set;}
}
您现在可以轻松地将其设置为OData服务,如下所示:

public class EmployeeDataService : DataService<DataModel>
公共类EmployeeDataService:DataService

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

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

看一看。特别是“公开数据库的转换”部分。您可以将实体对象展平为DTO,并让客户机针对该DTO模型运行查询


这就是你正在寻找的东西吗?

如果你有很长的复杂实体,那么手工创建投影就是一场噩梦<代码>自动映射无法工作,因为LINQ无法将其与IQueryable结合使用

这是一个完美的解决方案:

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


注意:这篇文章是几年前写的,到目前为止,
AutoMapper
可能已经内置了这样的功能。我只是没有时间,我现在自己检查一下。上述参考文章的灵感来源于AutoMapper本身的作者——因此,现在可能包含一些改进版本。总体概念似乎很棒,这个版本对我来说很好。

听起来是个不错的解决方案,但我无法让它工作。我怀疑这与我使用L2S并没有解决至少两个问题有关。我不能使用helper方法,因为上下文是包装在using中的,所以在查询集合时它将被释放。使用L2S或EF并不重要。您可以汇集来自任何源的数据。由于OData服务对象是“按请求”创建的,因此使用
using
语句是正确的方法,因为
DataModel
类实例将随请求一起创建和销毁。我不同意using语句,只要datacontext超出范围,即Get()之前,就会调用dispose方法有人打电话来。
    [Queryable]
    public IQueryable<DatabaseProductDTO> GetDatabaseProductDTO(ODataQueryOptions<DatabaseProductDTO> options)
    {
        // _db.DatabaseProducts is an EF table 
        // DatabaseProductDTO is my DTO object
        var projectedDTOs = _db.DatabaseProducts.Project().To<DatabaseProductDTO>();

        var settings = new ODataQuerySettings();
        var results = (IQueryable<DatabaseProductDTO>) options.ApplyTo(projectedDTOs, settings);

        return results.ToArray().AsQueryable();
    }
/odata/DatabaseProductDTO?$filter=FreeShipping eq true