Подтвердить что ты не робот

Создайте раскрывающийся список для MVC3 с использованием Entity Framework (.edmx Model) и Razor Views && Вставьте запись базы данных в несколько таблиц

После прочтения 100 статей о том, как создать список DropDown в MVC 3 с помощью Razor Views, я не смог найти тот, который соответствует моему делу. Поэтому после часов и часов поиска ответа я решил опубликовать этот вопрос, чтобы узнать, есть ли у кого ответ или может помочь мне. Спасибо заранее!

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

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

enter image description here

Задачи:

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

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

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

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

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

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

Это мое первое большое приложение MVC3, использующее модель платформы Entity.

Спасибо за ваше время. Я действительно ценю знающих пользователей на этом сайте.

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

4b9b3361

Ответ 1

Не переходите модели db непосредственно к вашим представлениям. Вам повезло, что вы используете 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"))

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

@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"))

Наконец, другой вариант - таблица Lookup. В принципе, вы сохраняете пары ключ-значение, связанные с типом поиска. Одним из примеров типа может быть пол, в то время как другой может быть государством и т.д. Мне нравится структурировать мои как это:

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

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

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

Ответ 2

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

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

Итак, как вы можете создать лучшее соединение?

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

Итак, вы создаете ViewModel с полями, которые вам нужны в представлении. Вы добавляете элементы SelectList, которые вам нужны для поиска. И вы добавляете их как SelectLists уже. Таким образом, вы можете запрашивать данные из LINK с поддержкой sourc, выбирать идентификатор и текстовое поле и сохранять его как список избранных: Вы получаете то, что вам не нужно создавать новый тип (словарь) в качестве поиска, и вы просто перемещаете 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 этого типа и зафиксировать изменения.

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

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