可以在DTO中使用ODataQueryOptions吗?

时间:2014-02-08 15:27:38

标签: 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 => u.UserId == userId)
            .OrderBy(o => o.Description))
            .Cast<ContentTypes>();

        return result;
   }

尝试应用ODataQueryOptions时收到错误500。由于该类已经继承ODataController,我甚至需要执行options.ApplyTo(...)

3 个答案:

答案 0 :(得分:1)

此解决方案是确保返回类型是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;
        }
    }

使用ODataQueryOptions的原因是我希望EF在数据库调用级别处理过滤。否则,我会返回所有记录,然后Queryable会返回,比如第一页结果。

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

正如@Schandlich指出的那样,这不适用于$select$expand

答案 1 :(得分:0)

根据@ 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;
    }
}

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

答案 2 :(得分:0)

我能够通过AutoMapper Project()扩展实现这一目标。 $ select,$ filter等都应用于数据库查询。

 [TestMethod]
        public void DataShaping_With_AutoMapper_And_OData_Select_Test()
        {
            OracleMonitor myMonitor = new OracleMonitor();
            myMonitor.IsActive = true;

            var dbcontext = new MyDbContext();
            
            var datasource = dbcontext.Datasouces;

            Assert.IsNotNull(datasource);

            SetupAutoMapper();

            var odataQuery = Extensions.CreateDummyODataQuery<DataSourceDTO>("$expand=Fields($select=Description)&$select=Name");

            var withShaping = datasource.Project().To<DataSourceDTO>();

            Assert.IsNotNull(withShaping);

            var withODataQuery = odataQuery.ApplyTo(withShaping);
            Assert.IsNotNull(withODataQuery);

            string strJson = JsonConvert.SerializeObject(withODataQuery);

            Assert.IsFalse(String.IsNullOrEmpty(strJson));
        }