Выберите запрос с подзапросом, который может вернуть список <string> - PullRequest
0 голосов
/ 24 января 2019

У меня есть две таблицы: Продукты и Изображения продуктов

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

Сущности выглядят следующим образом:

public class ProductDto
{
    public int Id { get; set; }

    public string Name { get; set; }

    public long ProductNumber { get; set; }

    public decimal? Size { get; set; }

    public string SizeMeasurement { get; set; }

    public decimal? Pack { get; set; }

    public List<string> PhotoFileNames { get; set; }
}

Здесь отображается запрос с ошибкой:

var query = from p in _productRepository.GetAll()
        let PhotoFileNames =  _productPhotoMapRepository.GetAll().DefaultIfEmpty()
            .Where(e => e.ProductId == p.Id).Select(e => e.FileName).ToList()
    where
    (string.IsNullOrWhiteSpace(input.Filter) || p.Name.Contains(input.Filter))
    select new
    {
        p.Id,
        p.ProductNumber,
        p.Name,
        p.Size,
        p.SizeMeasurement,
        p.Pack,
//I've also tried doing this but get same error:
//PhotoFileNames = _productPhotoMapRepository.GetAll().DefaultIfEmpty()
//                     .Where(e => e.ProductId == p.Id).Select(e => e.FileName).ToList()
        PhotoFileNames
    };

    var productList = await query.ToListAsync();

Я получаю следующую ошибку:

System.ArgumentException: Expression of type 'System.Collections.Generic.IAsyncEnumerable`1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable`1[System.String]' of method 'System.Collections.Generic.List`1[System.String] ToList[String](System.Collections.Generic.IEnumerable`1[System.String])'
Parameter name: arg0
   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0)
   at System.Linq.Expressions.MethodCallExpression1.Rewrite(Expression instance, IReadOnlyList`1 args)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitAndConvert[T](ReadOnlyCollection`1 nodes, String callerName)
   at Remotion.Linq.Parsing.RelinqExpressionVisitor.VisitNew(NewExpression expression)
   at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)

Я пытаюсь избежать использования цикла for по соображениям производительности.Если я полностью опущу PhotoFileNames, продукты вернутся без проблем.

Каков будет правильный способ получить желаемый результат для каждого продукта и всех имен файлов изображений, которые хранятся в другой таблице SQL?

Редактировать: добавлен контекст БД и классы моделей

public class Product
    {
        public int Id { get; set; } //Aka productId

        public string Name { get; set; }

        public long ProductNumber { get; set; }

        public decimal? Size { get; set; }

        public string SizeMeasurement { get; set; }

        public decimal? Pack { get; set; }
    }

       public class ProductPhotoMap 
        {
           public virtual long ProductPhotoId {get;set;}

            public virtual int DisplayOrder { get; set; }

            public virtual bool IsDefault { get; set; }     

            public virtual int ProductId { get; set; }
            public Product Product { get; set; }

            public virtual string FileName { get; set; }

        }

и в моем контексте:

    public virtual DbSet<Product> Products { get; set; }

    public virtual DbSet<ProductPhotoMap> ProductPhotoMappings { get; set; }

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Весь ваш запрос в полном беспорядке.Так что трудно угадать, чего вы на самом деле хотитеНо я предположил, что вам может понадобиться что-то следующее:

Итак, сначала обновите свой класс Product следующим образом:

public class Product
{
    public int Id { get; set; } //Aka productId

    public string Name { get; set; }

    public long ProductNumber { get; set; }

    public decimal? Size { get; set; }

    public string SizeMeasurement { get; set; }

    public decimal? Pack { get; set; }


    public ICollection<ProductPhotoMap> ProductPhotoMaps {get; set;}
}

Затем напишите запрос следующим образом:

var query = _productRepository.GetAll().Select(p => new ProductDto
       {
        Id = p.Id,
        ProductNumber = p.ProductNumber,
        Name = p.Name,
        Size = p.Size,
        SizeMeasurement = p.SizeMeasurement,
        Pack = p.Pack,
        PhotoFileNames = p.ProductPhotoMaps.Select(pp => pp.FileName).ToList()
    });

If(!string.IsNullOrWhiteSpace(input.Filter))
{
   query.Where(p => p.Name.Contains(input.Filter))
}

var productList = await query.ToListAsync();
0 голосов
/ 24 января 2019

.ToListAsync() не возвращает List<string>.Вы можете либо обновить свойство, либо использовать .ToList() не асинхронно.

...