Linq с ожиданием: в этом контексте поддерживаются только примитивные типы или типы перечисления

#c# #linq #model-view-controller

#c# #linq #модель-представление-контроллер

Вопрос:

У меня есть это исключение: невозможно создать постоянное значение типа ….ViewModels.Yarn.FilterNameDto’. В этом контексте поддерживаются только примитивные типы или типы перечисления.

ViewModels:

 public class YarnListViewModel
{
    public YarnListFilter YarnListFilter { get; set; }
    public IEnumerable<FilterNameDto> FilterNames { get; set; }
}

public class YarnListFilter
{
    public int? BrandId { get; set; }
    public string ProductName { get; set; }
}

public class FilterNameDto
{
    public string ProductName { get; set; }
}
  

В Contoller:

 List<FilterNameDto> nlnames = new List<FilterNameDto>
{
    new FilterNameDto { ProductName = "Farouche" },
    new FilterNameDto { ProductName = "La Parisienne" },
...
};

var filternamesdb = _context.YarnFullAdmins
                    .Where(n => n.ProductName != null)
                    .GroupBy(n => n.ProductName)
                    .Select(n => n.FirstOrDefault());
if (yarnListFilter.BrandId > 0)
    filternamesdb = filternamesdb.Where(b => b.BrandId == yarnListFilter.BrandId);

// Until here everything works fine

var filternamesdblist = filternamesdb.Select(n => new FilterNameDto
    {
        ProductName = n.ProductName,
    }).Except(nlnames).ToList(); // I remove the names who are in the nlnames list

nlnames.AddRange(filternamesdblist); // And I add them so they come out first

var filternames = filternamesdblist;
if (yarnListFilter.BrandId == null || yarnListFilter.BrandId == 1)
    filternames = nlnames;

var viewModel = new YarnListViewModel
{
FilterNames = filternames
};

    return View(viewModel);

  

.Исключение — моя проблема!

Вид:

 @Html.DropDownListFor(f => f.YarnListFilter.ProductName
, new SelectList(Model.FilterNames, "ProductName", "ProductName")
,"Filter by Name"
, new { @class = "form-control", @onchange = "this.form.submit();" })
  

Моя цель — сделать так, чтобы некоторые элементы (указанные в списке nlnames), которые на самом деле находятся в результате запроса (везде в этом списке), были первыми. Итак, я подумал, что удаляю их из списка, а затем добавляю их, чтобы они были первыми в списке.
Или есть (и я уверен, что есть) гораздо лучший способ добиться этого ?!?!?

Чтобы резюмировать это ясно и коротко: база данных возвращает Aaa, Bbb, Ccc, Ddd, Eee, и я хочу, чтобы Bbb, Ddd были первыми! Заранее спасибо за вашу помощь.

Ответ №1:

Проблема в том, что ваш объект nlnames не может быть преобразован во что-то, что понимает SQL Server. Чтобы обойти это, вы могли бы вызвать .ToList() перед .Except()

 var filternamesdblist = filternamesdb
    .Select(n => new FilterNameDto
    {
        ProductName = n.ProductName,
    })
    .ToList()
    .Where(n => !nlnames.Any(nl => nl.ProductName == n.ProductName))
    .ToList();
  

В качестве альтернативы вы можете изменить тип nlnames List<string> , который может быть понятен SQL Server:

 var nlnames = new List<string> { "Farouche", "La Parisienne" };

var filternamesdblist = filternamesdb
    .Where(n => !nlnames.Contains(n.ProductName))
    .Select(n => new FilterNameDto
    {
        ProductName = n.ProductName,
    })
    .ToList();
  

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

1. Спасибо @Adam. Никаких исключений. Но это не удалило имена из списка. Итак, теперь у меня их 2 раза! Есть идеи?

2. Я думаю, что это будет проблемой .Except() , возможно, попробуйте заменить его .Where(n => !nlnames.Any(nl => nl.ProductName == n.ProductName)) . Исключение, вероятно, будет ожидать, что объект будет равен, а ваш не будет таким, как filternamesdb поступает из базы данных и nlnames представляет собой жестко запрограммированный список

3. Нет, извините. С этим я возвращаюсь к своему исключению

4. .ToList() nlnames Для предотвращения возникновения этого исключения требуется вызов перед использованием

5. Вот и все. Вызов . ToList() и затем . Где работает отлично. Большое вам спасибо @Adam. Хорошего дня.