Помощь начинающим EF4 / CodeFirst / MVC3 - PullRequest
2 голосов
/ 27 марта 2011

Хотя мне нравится то, что я изучаю, я нахожу это трудным делом и мне нужна помощь

Я использовал эти два урока, которые, на мой взгляд, великолепны: http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx http://msdn.microsoft.com/en-us/data/gg685467

В настоящее время моя главная проблема / путаница:

У меня есть таблица / сущность CodeFirst, я не знаю, как правильно получить данные из других таблиц / сущностей для отображения в моих представлениях:

public class Car {
    public int ID { get; set; }
    public string Name { get; set; }

    public int EngineID { get; set; }
    public virtual Engine { get; set; }
}

public class Engine {
    public int ID { get; set; }
    public string Name { get; set; }
    public string Manufacturer { get; set; }
    // (plus a whole lot of other things)
}

Теперь, когда я создаю View for Cars (используя тип / опцию List), я получаю хороший автоматически сгенерированный список

@foreach (var item in Model) {
<tr>
    <td>@item.ID</td>
    <td>@item.Name</td>
    <td>@item.EngineID</td>
</tr>

Отлично ... за исключением того, что EngineID в основном бесполезен для зрителя, и я хочу показать Engine.Name вместо него

Итак, я предположил, что мог бы использовать ленивую загрузку EF:

<td>@item.Engine.Name</td>

К сожалению, когда я попробовал это, он говорит, что мой ObjectContext был удален, поэтому не может получить дальнейшие данные, требующие подключения

Затем я попытался перейти к контроллеру и включить Engine.Name

var cars = (from c in db.Cars.Include("Engine.Name") select c;

Что говорит мне: Entities.Engine не объявляет свойство навигации с именем 'Name'

...? Ложь

Include («Engine») работает нормально, но все, что мне нужно, это имя, а Include («Engine») загружает большое количество ненужных мне вещей

Ранее в такой ситуации я создал представление в БД для автомобиля, которое также включает в себя EngineName. Но с CodeFirst и моей noobness я не нашел способ сделать это

Как мне решить эту проблему?

Я подумал, что, возможно, смогу создать модель, почти идентичную сущности Car, но добавлю в нее Engine.Name. Это было бы неплохо, так как я мог бы затем использовать его в нескольких местах, но я не знаю, как его заполнить и т. Д.

Желание также изучить TDD, но вышесказанное уже расстраивает меня: p

PS Любые другие учебные ссылки или полезные материалы для чтения будут с благодарностью

1 Ответ

2 голосов
/ 27 марта 2011

Это не ложь, так как вы на самом деле пытаетесь включить свойство, которое находится на 2-м уровне ниже, не давая ему возможность перемещаться.Если вы позволите EF сгенерировать вашу БД с этой структурой, она, вероятно, создаст таблицу навигации, которая называется что-то вроде Car_Engine, и если вы включите имя без объекта, который он сопоставил, то у него не будет свойства навигации в новом объекте.

Простой способ обойти это:

(from c in db.Cars.Include("Engine") select new { c, EngineName = c.Engine.Name }

Если вы по-прежнему получаете ошибки свойств навигации, то вам может потребоваться убедиться, что вы правильно сопоставляете свою схему.Это можно сделать с помощью классов EntityTypeConfiguration, используя свободный API - очень мощный.

Это, конечно, не поможет при строгой типизации вашего автомобильного объекта для отображения в MVC.Если вы хотите обойти это, ваше внутреннее чувство правильно.Довольно часто используются модели представления, которые предназначены только для чтения (по своему дизайну, не обязательно должны быть установлены только для чтения), которые обеспечивают простое представление ваших данных.

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

Используя ваши viewmodels, вы можете иметь класс с именем CarSummaryView или что-то еще только с теми данными, которые вам нужны.Это также решает проблему уязвимости на вашем сайте.Он может быть легко заполнен вышеуказанным запросом.

PS Существует множество преимуществ использования моделей представления, помимо простой загрузки полной иерархии.Одним из самых больших преимуществ является то, что оно дает вам возможность избегать чрезмерных и заниженных сценариев.

Существует множество способов реализации моделей представления, но в качестве простого примера CarView:

public class CarView
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string EngineName { get; set; }
}

Это должно быть четко отделено от вашей модели сущности.В большом проекте у вас будет один проект viewmodels, который может вернуть докладчик, но в меньшем проекте они просто нужны на том же уровне, что и код службы.

Чтобы заполнить его непосредственно из запроса, вы можете сделать следующее

List<CarView> cars = (from c in db.Cars.Include("Engine.Name") select new CarView() { ID = c.ID, Name = c.Name, EngineName = c.Engine.Name }).ToList();
...