ASP.NET Web API возвращают запрашиваемые DTO? - PullRequest
9 голосов
/ 27 марта 2012

Я создал симпатичный маленький API с помощью ASP.NET Web 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 ]

7 голосов
/ 27 марта 2012

Не выбирайте все в памяти в первую очередь.Сделайте что-то вроде этого:

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

Кстати. Следующий код - это то, что вы хотите сделать один раз, например, в статическом конструкторе или в файле WebApiConfig.cs.

Mapper.CreateMap<Item, ItemDto>()
    .ForMember(itemDto => itemDto.Category, mce => mce.MapFrom(item => item.Category.Name));
3 голосов
/ 07 ноября 2013

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

Использовать return _itemRepository .GetItemsQuery () .project () К ();.

3 голосов
/ 04 апреля 2012

Если в коде, который мы видим (т. Е. Упорядочение и прием), выполняется только запрос, ваш код в порядке. Он будет отображать только результат (максимум 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...