Как вернуть несколько строк, используя LINQ lambda expression из SQL Server 2014?

#c# #sql-server #entity-framework #linq #automapper

#c# #sql-server #entity-framework #linq #automapper

Вопрос:

Я пытаюсь извлечь данные из SQL Server 2014, используя лямбда-выражение LINQ, которое является требованием моего проекта. Но поскольку я новичок в LINQ, мне кажется, я делаю что-то не так с приведенным здесь кодом, и я получаю сообщение об ошибке.

Я могу извлечь только одну строку без какой-либо ошибки, но если я поставлю условие для извлечения нескольких строк, то получу ошибку.

Вот мой код — это класс репозитория:

     public DettagliModel GetByIdDoc(int id)
    {
        using (var dbCtx = new USDevEntities())
        {
            var dettagli = dbCtx.Dettaglis.Where(x => x.IDDoc == id);

            if (dettagli != null)
            {
                return ConvertTo(dettagli); // Getting error here 
            }
            else
            {
                return null;
            }
        }
    }

    public DettagliModel ConvertTo(Dettagli entity)
    {
        var model = Mapper.Map<DettagliModel>(entity);
        return model;
    }
  

Я получаю эту ошибку:

Аргумент 1: не удается выполнить преобразование из ‘System.Linq.IQueryable’ to ‘DAL.Service.Сущность.Dettagli’ Core.Service

Эта ошибка возникает при написании кода, но если я помещу после

    .Where(x => x.IDDoc == id).FirstOrDefault();
  

затем ошибка исчезает.

Пожалуйста, подскажите мне, что я могу сделать, чтобы решить эту проблему, поскольку мне нужно получить несколько строк, поэтому я не могу использовать FirstOrDefault() метод. Спасибо.

Комментарии:

1. Используете ли вы automapper?

2. да, я использую его.

3. Я включил этот тег в ваш вопрос, потому что это актуально

4. Спасибо @octavioccl

Ответ №1:

Where метод расширения возвращает IQueryable<T> , что означает, что это более одного элемента. Если вы хотите сопоставить множественные объекты с другой моделью с помощью Automapper, то я предлагаю вам использовать ProjectTo<T> метод расширения:

 public IEnumerable<DettagliModel> ConvertTo(IQueryable<Dettagli> entities)
{

    return entities.ProjectTo<DettagliModel>().ToList();
}

public IEnumerable<DettagliModel> GetByIdDocs(int id)
{
    using (var dbCtx = new USDevEntities())
    {
        return ConvertTo(dbCtx.Dettaglis.Where(x => x.IDDoc == id));

    }

}
  

Комментарии:

1. Спасибо за ответ. Я пробовал ваш код, но строка ProjectTo<DettagliModel>() выдает ошибку, которая «Не содержит определения ProjectTo». Не могли бы вы, пожалуйста, рассказать мне, как это реализовать?

2. вам нужно добавить пространство имен. Я не помню названия. Подождите секунду

3. using AutoMapper.QueryableExtensions;

Ответ №2:

Во-первых, это никогда не будет равно null:

 var dettagli = dbCtx.Dettaglis.Where(x => x.IDDoc == id);
  

Кроме того, не возвращайте, null когда что-то есть IEnumerable<T> , используйте Enumerable.Empty<T>() .


Теперь ваш метод стремится вернуть одну, DettagliModel которая ConvertTo создается из одной Dettagli .

Возможно, вам потребуется изменить возвращаемый тип на IEnumerable<DettagliModel>

Теперь вы можете просто использовать .Select для проецирования объектов базы данных в свои собственные типы:

 return
    dettagli.Select(d => ConvertTo(d)); 
    //or just dettagli.Select(ConvertTo); if you like.
  

Это будет отложенная коллекция, поэтому я бы, вероятно, преобразовал ее в не отложенную, используя .ToList() в конце (а затем .AsReadOnly() или используя .ToArray() YMMV).

Ответ №3:

 .Where(x => x.IDDoc == id).ToList();
  

ВОЗВРАТ List<dbCtx.Dettaglis>