使用entity framework(.edmx模型)&Razor视图&&将数据库logging插入多个表创buildMVC3的下拉列表
在阅读了关于如何使用Razor Views在MVC 3中创buildDropDown列表的100篇文章之后,我找不到适合自己的案例。 所以在search答案的小时数和小时数之后,我决定发布这个问题,看看有没有人有答案,或者可以帮助我。 先谢谢你!!!
情况:我最终试图创build一个视图来添加一个员工到数据库。
下面是我正在使用的.EDMX模型的图像(将由create()使用的表格):
目标:
-
创build一个员工(我有CreateFshtml(强types)用部分视图为StaffNotifycheckbox){我在创build视图通知部分视图中使用单独的@model不知道,如果这是安全的? @model ShadowVenue.Models.Employee&@model ShadowVenue.Models.StaffNotify)
-
为StaffTypeId创build一个下拉框(它将从Table“StaffType”(它有一对多的关系)插入[StaffTypeId]值,但是会在下拉菜单中显示[Type]string值)
-
为GenderId创build一个下拉框(它将从表格“性别”(具有一对多关系)中插入[GenderId]值),但会在下拉列表中显示[Gender]string值)
-
将logging插入到数据库中(我在StaffId主键上有一个1对1关系的单独表中的员工通知)
我似乎遇到了这个控制器代码的麻烦。
我不确定是否应该在EDMX模型中创build存储过程,或者提出一些查询或方法的语法,不知道哪个是最好的方法。
这是我的第一个大型MVC3应用程序使用entity framework模型。
感谢您的时间。 我真的很感激这个网站的知识渊博的用户。
(如果您需要知道任何导航属性名称,以帮助解决scheme只是让我知道,我会提供给你)
不要直接将db模型传递给您的视图。 你很幸运能够使用MVC,所以使用视图模型进行封装。
像这样创build一个视图模型类:
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首先对其进行脚手架),将inheritance的types更改为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"))
更新每个评论
对于性别,如果在上面build议的视图模型中没有genderTypes,也可以这样做(尽pipe如此,也许我会在视图模型中生成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"))
最后,另一个选项是查找表。 基本上,您保持与查找types关联的键值对。 一个types的例子可能是性别,而另一个可能是国家等。我喜欢这样构造我的:
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
当一组数据不经常改变时,我喜欢使用这些表,但仍需要不时地列举。
希望这可以帮助!
呃,实际上我不得不说David对他的解决scheme是对的,但是有一些话题让我感到困扰:
- 你不应该把你的模型发送到视图=>这是正确的
- 如果你创build一个
ViewModel
,并且在ViewModel
包含Model作为成员,那么你就有效地将你的模型发送到View =>这是不好的 - 使用字典将选项发送到视图=>这不是很好的风格
那么你怎么能创造一个更好的耦合?
我将使用类似AutoMapper
或ValueInjecter的工具来映射ViewModel
和Model。 AutoMapper
似乎有更好的语法和感觉,但目前的版本缺乏一个非常严重的话题:它不能执行从ViewModel
到模型的映射(在某些情况下,如展平等,但这是脱离主题)所以目前我更喜欢使用ValueInjecter
。
所以你用ViewModel
需要的字段创build一个ViewModel
。 您将查找所需的SelectList项添加。 而且你已经将它们添加为SelectLists。 因此,您可以从支持LINQ的源代码查询,selectID和文本字段并将其存储为select列表:您可以获得不必创build新的types(字典)作为查找,而只需从视图中移动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 )
回到你的方法在控制器的后期元素,你必须采取你的ViewModel
types的参数。 然后你检查validation。 如果validation失败,则必须记住重新填充viewModel.StaffTypes
SelectList,因为在inputpost函数时该项目将为空。 所以我倾向于把这些人口的东西分成一个函数。 如果有什么错误,你只需要return new View(viewModel)
。 MVC3发现的validation错误将自动显示在视图中。
如果您有自己的validation代码,则可以通过指定属于哪个字段来添加validation错误。 检查ModelState
上的文档以获取相关信息。
如果viewModel
有效,则必须执行下一步:
如果是创build新项目,则必须从viewModel
填充模型(最适合的是ValueInjecter
)。 然后,您可以将其添加到该types的EF集合并提交更改。
如果你有一个更新,你会得到当前的数据库项目第一个模型。 然后,您可以将viewModel
的值复制回模型(再次使用ValueInjecter
可以让您快速完成)。 之后,您可以SaveChanges
并完成。
随意问,如果有什么不清楚。