C# 4.0 是否可以将ODataQueryOptions与DTO';s

C# 4.0 是否可以将ODataQueryOptions与DTO';s,c#-4.0,odata,dto,C# 4.0,Odata,Dto,ContentType-->EF型号 ContentTypes-->DTO 在我的OData控制器中: public Task<IQueryable<ContentTypes>> Get(ODataQueryOptions<ContentTypes> options) { var result = options.ApplyTo(_repository.Query().Get() .Where(u =>

ContentType
-->EF型号

ContentTypes
-->DTO

在我的OData控制器中:

   public Task<IQueryable<ContentTypes>> Get(ODataQueryOptions<ContentTypes> options) 
   {
        var result = options.ApplyTo(_repository.Query().Get()
            .Where(u => u.UserId == userId)
            .OrderBy(o => o.Description))
            .Cast<ContentTypes>();

        return result;
   }
公共任务获取(ODataQueryOptions选项)
{
var result=options.ApplyTo(_repository.Query().Get())
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description))
.Cast();
返回结果;
}

尝试应用
ODataQueryOptions
时,我收到一个错误500。既然类已经继承了
ODataController
,我甚至需要执行
选项。ApplyTo(…)

根据@ElHaix的答案更新。我强烈建议不要使用AutoMapper从这样的数据源进行映射。这还假设应用于存储库的查询是在调用数据库之前应用的

[Queryable]
public virtual IHttpResult Get()
{
    var userId = 102;   // mock

    try
    {
        var results = _uow.Repository<ContentType>()
            .Query()
            .Get()
            .Where(u => u.UserId == userId)
            .OrderBy(o => o.Description)
            .Select(x => new ContentTypeDTO() 
            {
                //projection goes here
            });

        return this.Ok(results);
    }
    catch (Exception ex)
    {
        throw ex;
    }
}
[可查询]
公共虚拟IHttpResult Get()
{
var userId=102;//mock
尝试
{
var results=\u uow.Repository()
.Query()
.Get()
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description)
.Select(x=>newcontenttypedto()
{
//投影在这里
});
返回这个。Ok(结果);
}
捕获(例外情况除外)
{
掷骰子;
}
}

另外,我会尝试对ElHaix的答案执行$select。

解决方案是确保返回类型是DTO的类型,并且
ODataQueryOptions
应用于EF实体。然后我使用Automapper将结果映射到DTO

我已经根据@Schandlich的建议更新了答案,但是仍然存在一些问题:

    [Queryable]
    public virtual IHttpActionResult Get(ODataQueryOptions<ContentType> options)
    {
        var userId = 102;   // mock

        try
        {
            var results = options.ApplyTo(_uow.Repository<ContentType>()
                .Query()
                .Get()
                .Include(u => u.User)
                .Where(u => u.UserId == userId)
                .OrderBy(o => o.Description)).Cast<ContentType>()
                .Select(x => new ContentTypeDTO()
                {
                    //projection goes here
                    ContentTypeId = x.ContentTypeId,
                    Description = x.Description,
                    UserDTO = new UserDTO 
                    { 
                        UserId = x.UserId,
                        UserName = x.User.UserName
                    }
                });

            return this.Ok(results);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
[可查询]
公共虚拟IHttpActionResult获取(ODataQueryOptions选项)
{
var userId=102;//mock
尝试
{
var results=options.ApplyTo(_uow.Repository())
.Query()
.Get()
.包括(u=>u.User)
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description)).Cast()
.Select(x=>newcontenttypedto()
{
//投影在这里
ContentTypeId=x.ContentTypeId,
描述=x.描述,
UserDTO=新的UserDTO
{ 
UserId=x.UserId,
UserName=x.User.UserName
}
});
返回这个。Ok(结果);
}
捕获(例外情况除外)
{
掷骰子;
}
}
使用
ODataQueryOptions
的原因是我希望EF在数据库调用级别处理向下过滤。否则,我将返回所有记录,然后
Queryable
将返回,比如结果的第一页

我删除了Automapper代码,但很好奇为什么不使用它


然而,正如@Schandlich所指出的,这对
$select
$expand
不起作用,我可以通过AutoMapper Project()扩展实现这一点$select、$filter等都应用于数据库查询

[TestMethod]
带有自动映射和OData选择测试()的公共无效数据形状
{
OracleMonitor myMonitor=新建OracleMonitor();
myMonitor.IsActive=true;
var dbcontext=new MyDbContext();
var datasource=dbcontext.Datasouces;
IsNotNull(数据源);
SetupAutoMapper();
var odataQuery=Extensions.CreateDummyODataQuery($expand=Fields($select=Description)和$select=Name);
var withShaping=datasource.Project().To();
Assert.IsNotNull(带形状);
var withODataQuery=odataQuery.ApplyTo(带形状);
Assert.IsNotNull(带ODataQuery);
字符串strJson=JsonConvert.SerializeObject(withODataQuery);
Assert.IsFalse(String.IsNullOrEmpty(strJson));

}
使用
[Queryable]
属性并删除
选项.ApplyTo()
,我从服务器获得31行。由于我想在服务器端应用过滤,使用
options.ApplyTo()
,将执行请求10条记录的sql查询(而不是稍后在客户端进行过滤)。EF过滤器随后出现的原因是因为您处理投影的方式。看看我上面贴的答案。我还会查看您的存储库,确保其中没有ToList()或其他强制执行方法。另外,当您使用$select或$expand时,这将中断,因为结果将不是ContentType类型。@Schandlich-您的建议部分有效,并且当我排除
选项时。ApplyTo()
,我不会返回所有其他OData信息,例如
$inlinecount=allpages
的值,因此没有分页详细信息。我不想返回数据库中的所有记录,然后在客户端进行筛选。有数千条记录的情况又如何?执行
$select
$expand
失败是正确的。我怎样才能让它工作呢。另外,为什么不使用Automapper来做一些工作呢?这里有一篇关于为什么不使用Automapper的好文章。分页不起作用的原因是,在应用分页之前的某个时刻,查询已经命中数据库。我不知道是AutoMapper导致了这个问题,还是您的存储库导致了这个问题。我可能是演员的陈述。我会努力让它开箱即用,而不是试图强制展开和选择以使用您的设置。这就是我编写和使用的解决方案。我创建自己的接口而不是IRepository,而不是从控制器调用EF。实现该接口的数据源只执行一个干净的项目