ASP.NET Web API返回可查询的DTO?

时间:2012-03-27 17:13:39

标签: asp.net linq entity-framework asp.net-web-api

我使用ASP.NET Web API构建了一个不错的小API,但我想从我的上下文(实体框架)AsQueryable返回实体是不对的,所以我将所有内容映射到DTO对象。

但是我不太明白:如何保持我的上下文可查询,但仍然只返回DTO而不是实体?或者这不可能吗?

这是我的代码:

public IQueryable<ItemDto> Get()
{
    using (EfContext context = new EfContext())
    {
        Mapper.CreateMap<Item, ItemDto>()
            .ForMember(itemDto => itemDto.Category, mce => mce.MapFrom(item => item.Category.Name));

        IEnumerable<ItemDto> data = Mapper.Map<IEnumerable<Item>, IEnumerable<ItemDto>>(context.Items
            .OrderByDescending(x => x.PubDate)
            .Take(20));

        return data.AsQueryable();
    }
}

正如您所看到的,我加载数据,并使那个小IEnumerable集合可查询。问题是为这段代码生成的查询可能效率很低,因为它首先加载所有项(或至少20个第一项),然后过滤输出。

我希望我尽可能好地描述我的问题,这有点难以解释。我在Google上找不到任何相关内容。

3 个答案:

答案 0 :(得分:7)

不要先选择内存中的所有内容。做这样的事情:

public IQueryable<ItemDto> Get()
{
    using (EfContext context = new EfContext())
    {
        var query = from item in context.Items
                    select Mapper.Map<Item, ItemDto>(item)

        return query.OrderByDescending(x => x.PubDate).Take(20));
    }
}

BTW以下代码是您想要执行的操作,例如在静态构造函数或WebApiConfig.cs文件中。

Mapper.CreateMap<Item, ItemDto>()
    .ForMember(itemDto => itemDto.Category, mce => mce.MapFrom(item => item.Category.Name));

答案 1 :(得分:3)

如果在我们看到的代码(即订购和Take)中进行了唯一的查询,那么您的代码就可以了。它只会映射结果(最多20个)。但是,由于您要返回IQueryable,我假设您想进一步查询结果。可能是OData样式参数吗?

最多20个项目你可能最好不要编写任何代码。其余查询将作为对象查询执行。但是,如果您决定删除该约束(最多20个),或者在进行进一步查询后将其放置,则这种方式效率低下。

基本上,如果您希望在EF数据库中运行所有查询,则需要在查询链的最末端移动映射。

您可以做的实际上是返回实际的实体对象

    public IQueryable<ItemDto> Get()
    {
        using (EfContext context = new EfContext())
        {
            return context.items
                       .OrderByDescending(x => x.PubDate)
                       .Take(20));
         }
     }

告诉MVC如何在MediaTypeFormatter中序列化它。在这里你可以使用AutoMapper。

答案 2 :(得分:3)

http://dotnetplusplus.wordpress.com/2013/08/30/odata-web-apis-with-automapper-3/

使用return _itemRepository                 .GetItemsQuery()                 的。项目()为了();