Создать выпадающий список для MVC3, используя Entity Framework (модель .edmx) и Razor Views && Вставить запись базы данных в несколько таблиц - PullRequest
49 голосов
/ 16 марта 2011

После прочтения сотен статей о том, как создать DropDown List в MVC 3 с Razor Views, я не смог найти тот, который подходит для моего случая.

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

Вот изображение модели .EDMX, которую я использую (таблицы, которые будут использоваться create ().):

enter image description here

Цели:

  1. Создать сотрудника (у меня есть Create.cshtml (строго типизированный), созданный с частичным представлением для флажков StaffNotify) {Я использую отдельную @model в представлении частичного уведомления из представления создания, не уверен, если это безопасно ??? @model ShadowVenue.Models.Employee & @model ShadowVenue.Models.StaffNotify)

  2. Создайте раскрывающийся список для StaffTypeId (который будет вставлять значение [StaffTypeId] из таблицы «StaffType» (который имеет отношение 1 ко многим), но будет отображать строковое значение [Type] в раскрывающемся списке))

  3. Создайте раскрывающийся список для GenderId (который будет вставлять значение [GenderId] из таблицы «Genders» (которая имеет отношение 1 ко многим), но в раскрывающемся списке будет отображать строковое значение [Gender])

  4. Вставить запись в базу данных (у меня есть уведомления персонала в отдельной таблице с отношением 1: 1 в первичном ключе StaffId)

Кажется, у меня проблемы с кодом контроллера для этого.

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

Это мое первое большое приложение MVC3 с использованием Entity Framework Model.

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

Ответы [ 2 ]

75 голосов
/ 16 марта 2011

Не передавайте модели БД непосредственно вашим взглядам. Вам повезло, что вы используете MVC, так что инкапсулируйте, используя модели представления.

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

public class EmployeeAddViewModel
{
    public Employee employee { get; set; }
    public Dictionary<int, string> staffTypes { get; set; }
    // really? a 1-to-many for genders
    public Dictionary<int, string> genderTypes { get; set; }

    public EmployeeAddViewModel() { }
    public EmployeeAddViewModel(int id)
    {
        employee = someEntityContext.Employees
            .Where(e => e.ID == id).SingleOrDefault();

        // instantiate your dictionaries

        foreach(var staffType in someEntityContext.StaffTypes)
        {
            staffTypes.Add(staffType.ID, staffType.Type);
        }

        // repeat similar loop for gender types
    }
}

Контроллер:

[HttpGet]
public ActionResult Add()
{
    return View(new EmployeeAddViewModel());
}

[HttpPost]
public ActionResult Add(EmployeeAddViewModel vm)
{
    if(ModelState.IsValid)
    {
        Employee.Add(vm.Employee);
        return View("Index"); // or wherever you go after successful add
    }

    return View(vm);
}

Затем, наконец, в вашем представлении (которое вы можете использовать Visual Studio, чтобы сначала создать его), измените унаследованный тип на ShadowVenue.Models.EmployeeAddViewModel. Кроме того, для раскрывающихся списков используйте:

@Html.DropDownListFor(model => model.employee.staffTypeID,
    new SelectList(model.staffTypes, "ID", "Type"))

и аналогично для раскрывающегося списка полов

@Html.DropDownListFor(model => model.employee.genderID,
    new SelectList(model.genderTypes, "ID", "Gender"))

Обновление по комментариям

Что касается пола, вы также можете сделать это, если в описанной выше модели представлений вы не можете использовать значения гендерных типов (хотя, подумав, возможно, я бы сгенерировал эту сторону сервера в модели представлений как IEnumerable). Таким образом, вместо new SelectList... ниже вы бы использовали IEnumerable.

@Html.DropDownListFor(model => model.employee.genderID,
    new SelectList(new SelectList()
    {
        new { ID = 1, Gender = "Male" },
        new { ID = 2, Gender = "Female" }
    }, "ID", "Gender"))

Наконец, еще одна опция - это таблица поиска. По сути, вы сохраняете пары ключ-значение, связанные с типом «Уточняющий запрос». Одним из примеров типа может быть пол, а другим может быть State и т. Д. Мне нравится структурировать мой тип следующим образом:

ID | LookupType | LookupKey | LookupValue | LookupDescription | Active
1  | Gender     | 1         | Male        | male gender       | 1
2  | State      | 50        | Hawaii      | 50th state        | 1
3  | Gender     | 2         | Female      | female gender     | 1
4  | State      | 49        | Alaska      | 49th state        | 1
5  | OrderType  | 1         | Web         | online order      | 1

Мне нравится использовать эти таблицы, когда набор данных меняется не очень часто, но время от времени его необходимо перечислять.

Надеюсь, это поможет!

23 голосов
/ 16 марта 2011

Ну, на самом деле я должен сказать, что Дэвид прав в своем решении, но есть некоторые темы, которые меня беспокоят:

  1. Вы никогда не должны отправлять свою модель на просмотр => Это правильно
  2. Если вы создаете ViewModel и включаете Модель в качестве члена в ViewModel, то вы фактически отправили свою модель в View => это BAD
  3. Использование словарей для отправки параметров в представление => это не очень хороший стиль

Так как же вы можете создать лучшую связь?

Я бы использовал такой инструмент, как AutoMapper или ValueInjecter , чтобы отобразить между ViewModel и моделью. AutoMapper, кажется, имеет лучший синтаксис и ощущения к нему, но в текущей версии отсутствует очень серьезная тема: невозможно выполнить отображение из ViewModel в модель (при определенных обстоятельствах, таких как выравнивание и т. д., но это не по теме) Поэтому в настоящее время я предпочитаю использовать ValueInjecter.

Итак, вы создаете ViewModel с полями, которые вам нужны в представлении. Вы добавляете элементы SelectList, которые вам нужны, в качестве поисков. И вы добавляете их как списки выбора уже. Таким образом, вы можете сделать запрос из источника с поддержкой LINQ, выбрать идентификатор и текстовое поле и сохранить его в виде списка выбора: Вы получаете, что вам не нужно создавать новый тип (словарь) для поиска, и вы просто перемещаете new SelectList из представления в контроллер.

  // StaffTypes is an IEnumerable<StaffType> from dbContext
  // viewModel is the viewModel initialized to copy content of Model Employee  
  // viewModel.StaffTypes is of type SelectList

  viewModel.StaffTypes =
    new SelectList(
        StaffTypes.OrderBy( item => item.Name )
        "StaffTypeID",
        "Type",
        viewModel.StaffTypeID
    );

В представлении вам просто нужно позвонить

@Html.DropDownListFor( model => mode.StaffTypeID, model.StaffTypes )

Вернувшись к элементу post вашего метода в контроллере, вы должны принять параметр типа вашего ViewModel. Затем вы проверите для проверки. Если проверка не пройдена, вы должны не забыть повторно заполнить viewModel.StaffTypes SelectList, потому что этот элемент будет нулевым при входе в функцию post. Поэтому я склонен разделять эти популяции на функции. Вы просто перезвоните return new View(viewModel), если что-то не так. Ошибки проверки, найденные MVC3, будут автоматически отображаться в представлении.

Если у вас есть собственный код проверки, вы можете добавить ошибки проверки, указав, к какому полю они относятся. Проверьте документацию по ModelState, чтобы получить информацию об этом.

Если viewModel действителен, вы должны выполнить следующий шаг:

Если это создание нового элемента, вы должны заполнить модель из viewModel (лучше всего подходит ValueInjecter). Затем вы можете добавить его в коллекцию EF этого типа и зафиксировать изменения.

Если у вас есть обновление, вы сначала получаете текущий элемент БД в модель. Затем вы можете скопировать значения из viewModel обратно в модель (снова с помощью ValueInjecter вы сделаете это очень быстро). После этого вы можете SaveChanges и все готово.

Не стесняйтесь спрашивать, если что-то неясно.

...