LINQ to Entities ToString () - Ни одно из предложенных решений не работает? - PullRequest
6 голосов
/ 04 сентября 2011

Я публикую это больше, потому что я хотел бы узнать больше, потому что мой обходной путь был в основном избегать использования LINQ to Entities! Было бы хорошо, если бы я мог использовать это все же. Так что если кто-нибудь может просветить меня ..

Я работаю над приложением ASP.Net MVC 3 (моим первым), использующим Entity Framework с первым кодом в качестве модели данных. Это будет интернет-магазин, и я работаю над контроллером «Администратор», где, будучи администратором, вы сможете редактировать продукты и т. Д. Когда дело доходит до добавления нового продукта, вы должны указать категорию, что означает выпадающий список категорий.

Я начал с того, что просто возвратил коллекцию IEnumerable категорий в ViewBag, основываясь на информации, которую я нашел здесь . Это казалось действительно хорошим способом приблизиться к вещам.

Но я получил ту же ошибку, которую вы увидите ниже. Поэтому, следуя предложению, которое я прочитал в Интернете, я создал отдельную модель специально для создания новых и редактирования существующих продуктов. Коллекция Categories используется для построения выпадающего списка в представлении.

public class ProductModel
{
    public int Id { get; set; }
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public double Price { get; set; }
    public bool IsVisible { get; set; }

    public IEnumerable<SelectListItem> Categories
    {
        get
        {
            return new DataAccess()
                .Categories
                .OrderBy(c => c.Description)
                .Select(c => new SelectListItem
                    {
                        Value = c.Id.ToString(),
                        Text = c.Description
                    });
        }
    }
}

Это приводит к следующему сообщению об ошибке: « LINQ to Entities не распознает метод метода System.String ToString ()», и этот метод нельзя преобразовать в выражение хранилища. ». Одним из предлагаемых онлайн-решений было использование методов SqlFunction, предоставляемых Entity Framework. Поэтому я попробовал это вместо ...

    public IEnumerable<SelectListItem> Categories
    {
        get
        {
            return new DataAccess()
                .Categories
                .OrderBy(c => c.Description)
                .Select(c => new SelectListItem
                    {
                        Value = SqlFunctions.StringConvert((double)c.Id),
                        Text = c.Description
                    });
        }
    }

Но это приводит к этому сообщению об ошибке: " Указанный метод 'System.String StringConvert (System.Nullable`1 [System.Double])" для типа "System.Data.Objects.SqlClient.SqlFunctions' невозможно перевести в выражение хранилища LINQ to Entities.".

Я даже пытался добавить свойство только для чтения в класс данных с именем IdAsString , но это, очевидно, делает Entity Framework очень несчастным!

В конце концов, я понял, что это не стоит того времени, которое я вкладывал в него, и просто перестал использовать LINQ вообще. Это прекрасно работает, но было бы неплохо узнать, есть ли «правильный» способ сделать это, который действительно работает!

Это мое текущее рабочее решение:

    public IEnumerable<SelectListItem> Categories
    {
        get
        {
            var dal = new DataAccess();
            var categories = dal.Categories;
            var items = new List<SelectListItem>();

            foreach (var category in categories)
                items.Add(new SelectListItem
                    {
                        Value = category.Id.ToString(),
                        Text = category.Description
                    });

            return items;
        }
    }

Так что, если кто-то уже делает это и думает, что делает это "правильным" способом, то я хотел бы знать, что вы думаете!

1 Ответ

11 голосов
/ 04 сентября 2011

Материализация запроса перед вызовом ToString сделает последнюю часть запросом, не относящимся к объектам. Вы могли бы оптимизировать это, только выбрав идентификатор и описание, затем вызвав AsEnumerable и затем получив элементы selectlist.

    return new DataAccess() 
        .Categories 
        .OrderBy(c => c.Description)
        .AsEnumerable()
        .Select(c => new SelectListItem 
            { 
                Value = c.Id.ToString(), 
                Text = c.Description 
            }); 
...