MVC4,EF:创建具有 "hierarchical" 一对多关系的新对象

MVC4, EF : Create new object with "hierarchical" one-to-many relationship

我在创建对象时遇到问题。我的实体具有 "hierarchical" 一对多关系。一个部门可以属于另一个部门。 这是我的实体:

    //Properties
    [Key]
    [Column(Order = 0)]
    public int DivisionId { get; set; }

    [Required]
    [MaxLength(30)]
    [Column("DivisionName", Order = 2)]
    public string Name { get; set; }

    //Navigation properties
    public virtual Division ParentDivision { get; set; }

这是我创建新部门的方法:

public ActionResult Create()
    {
        ViewBag.ParentDivision = new SelectList(db.Divisions, "DivisionId", "Name");
        return View();
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Division division)
    {            
        if (ModelState.IsValid)
        {
            db.Divisions.Add(division);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.ParentDivision = new SelectList(db.Divisions, "DivisionId", "Name", division.ParentDivision.DivisionId);
        return View(division);
    }

在这种情况下,当我尝试创建属于另一个部门的部门时,出现 "Object reference not set to an instance of an object." 错误。

我也试过像这样更改 ViewBag:

ViewBag.ParentDivision = new SelectList(db.Divisions, "ParentDivision.DivisionId", "Name", division.ParentDivision.DivisionId);

这里创建了对象,但是没有父级划分...

我真的很困惑......如果有人有任何想法......提前谢谢你。

这与它是一种自引用关系这一事实无关。如果尚未设置 ParentDivision,它将为 null,而 null 没有 DivisionId 属性,因此您的例外。

您需要在引用 属性 之前进行空值检查。在这种情况下,最简单的方法可能是使用三元:

division.ParentDivision != null ? division.ParentDivision.DivisionId : null

但是,无论如何,您不需要设置 selected 值。 Razer 会自动处理此问题。您也不需要创建实际的 SelectListHtml.DropDownListFor 需要的只是一个 IEnumerable<SelectListItem>。如果你传递它,助手将负责创建 SelectList 并设置适当的 selected 值(如果适用)。

ViewBag.ParentDivision = db.Divisions.Select(m => new SelectListItem { Value = m.DivisionId, Text = m.Name });

然后:

@Html.DropDownListFor(m => m.ParentDivisionId, (IEnumerable<SelectListItem>)ViewBag.ParentDivision)

这又引出了另一件事。您目前没有要实际绑定的 属性。您不能直接使用 ParentDivision,因为 select 列表只会 post 返回 id,而不是完整的 ParentDivision 实例。您需要一个 属性 来将 posted id 绑定到,无论如何,这是包含在您的实体中的一个好习惯:

[ForeignKey("ParentDivision")]
public int ParentDivisionId { get; set; }
public virtual Division ParentDivision { get; set; }