具有强类型MVC的实体框架

Zac*_*son 12 .net c# asp.net asp.net-mvc entity-framework

我正在使用ASP.NET MVC和ADO.NET实体框架.

我希望我的视图和控制器强类型.

但是我该如何处理实体关联呢?

这是一个简单的例子:

一个人有一个部门.部门有零个或多个人.

人员和部门实体的实体数据模型

我的控制器将一个Person对象的实例和所有Department对象的集合传递给View.

public class PersonController : Controller
{
    ...

    //
    // GET: /Person/Create

    public ActionResult Create()
    {
        Person Model = new Person();
        Model.Id = Guid.NewGuid();
        ViewData["Departments"] = db.Department;
        return View(Model);
    } 
    ...
}
Run Code Online (Sandbox Code Playgroud)

我的视图有一个"部门"DropDownList,所有部门都作为选项.

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Id">Id:</label>
            <%= Html.TextBox("Id") %>
            <%= Html.ValidationMessage("Id", "*") %>
        </p>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name") %>
            <%= Html.ValidationMessage("Name", "*") %>
        </p>
        <p>
            <label for="Department">Family:</label>
            <%= Html.DropDownList("Department", new SelectList((IEnumerable)ViewData["Departments"], "Id", "Name"))%>
            <%= Html.ValidationMessage("Department", "*")%>
        </p>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>
Run Code Online (Sandbox Code Playgroud)

但是,发布到控制器的Person对象没有Department并且失败了!

public class PersonController : Controller
{
    ...

    //
    // POST: /Person/Create

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Person Model)
    {
        try
        {
            db.AddToPerson(Model);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

为什么从DropDownList"Department"中选择的部门不会自动添加到模型Person?

如何将ADO.NET实体框架和ASP.NET MVC与强类型视图和控制器一起使用?

bbm*_*mud 5

我会尽力引导你离开MVC,因为这就是问题所在,我相信

在Create()方法中,您可以从数据库创建Person对象和Departments列表,然后将这两个对象传递给View.View从Department列表中获取数据并使用它来呈现HTML表单 - 仅使用Id和Name.

在下一步中,表单作为值 - 密钥对的集合(标准POST)提交给服务器.路由引擎从action属性获取请求的url并将其解析为PersonController.Create(Person Model)操作.此方法的参数是Person,因此数据绑定器启动,创建Person类的新实例,并尝试将传入数据与Person的属性进行匹配.在Department的情况下,传入的值是部门的Id(因为这是您设置为DropDownList的值成员),而Person类的属性Department可能是Department类型.这是一个不匹配,所以它不能填充属性,它是空的.

正如您所看到的,这不是DropDownList的限制,问题是您不能将所有Department数据传递给DropDownList并在保存期间重新创建它(就像使用Person一样),因为POST请求的性质,以及这就是为什么DropDownList只从每个Department(值和名称)中获取两个值.

我通常的解决方案:通常我的模型与我的业务对象不是同一类,我通过在模型上有两个属性来做到这一点:只获取IEnumerable属性,以及另一个DepartmentId属性(get/set).然后我像这样使用它:

<%= Html.DropDownList("DepartmentId", Model.Departments) %>
Run Code Online (Sandbox Code Playgroud)

然后在保存操作中,我使用DepartmentId从数据库中获取部门,将其分配给Person并保存.

在你的情况下(模型是业务对象)我可能不会尝试自动将Department绑定到Person模型,而只是抓住Id并自己完成.

这只是一个猜测(我不是EF专家),但我认为你可能有另一个问题:如果db是Controller上的一个字段,并且在每次请求时重新创建它,这可能是一些不必要的开销.我希望它不会每次都打开数据库连接,请检查它.

希望有所帮助


nki*_*kes 2

我还没有发现开箱即用的 DropDownList 帮助器与模型绑定配合得很好。在将更改提交到存储库或数据库之前,我始终必须从 ViewData 中获取 DropDownList 的值,并在控制器中手动映射该值。

大多数时候,我使用 DropDownList 来显示自定义类型关系的选项(例如人员的部门)。MVC 无法仅根据列表中所选项目的值来了解如何映射对象。相反,您必须使用所选值获取该实体并自行映射。我不知道这是否是这里的问题,而且我还没有尝试过将列表绑定到仅使用简单类型作为选项(例如要购买的产品数量或类似内容)的模型,但我很好奇了解有关此特定问题的更多信息以及其他人如何使用下拉列表管理模型绑定。