5

我一直在寻找这个问题的答案 2 天了。我什至不确定到底出了什么问题,但我想我可能已经查明了可能的罪魁祸首。

我的程序是一个数据库跟踪器/管理器,它将跟踪我公司的设备。用户可以查询、创建和编辑设备。现在,查询数据库是可行的,但是当我尝试添加或更新数据库时,程序会抛出验证错误(我将在下面详细介绍)。

我有一个设备类,它有许多可以为空的属性(因为用户在创建新条目时可能不知道其中的许多属性,我们几乎所有属性都可以为空)并连接到(使用外键和延迟加载/“虚拟” ) 用于帮助规范化数据库的其他一些表。

以下是一些帮助的缩写代码:

设备型号:

public class Equipment
{
    public int EquipmentId { get; set; } //required

    public string Company { get; set; } //required

    public bool Verified { get; set; } //required

    (...other non-required attributes...)


    //The following two attributes are where my problems are I believe
    [ForeignKey("PAU")]
    public int PAUId { get; set; } //required and Foreign Key    

    //This is not required (but is FK to the related table) if the user doesn't know
    [ForeignKey("Division")]
    public Nullable<int> DivisionId { get; set; }


    //These are the lazy loading connections to the other tables in the database

    public virtual Division Division { get; set; }

    public virtual PAU PAU { get; set; }
}

部门型号:本表仅包含我公司5个不同部门及相关ID。

public class Division
{
    public Division()
    {
        this.Equipments = new HashSet<Equipment>();
    }

    //These are non-nullable/required fields
    public int DivisionId { get; set; }
    public string DivisionName { get; set; }

    public virtual ICollection<Equipment> Equipments { get; set; }
}

PAU 模型:此模型包含 PAU#s 以及相关的描述和 ID。

public class PAU
{
    public PAU()
    {
        this.Equipments = new HashSet<Equipment>();
    }

    //These are non-nullable/required fields
    public int PAUId { get; set; }
    public string PAUNumber { get; set; }
    public string PAUDescription { get; set; }

    public virtual ICollection<Equipment> Equipments { get; set; }
}

设备控制器:

public class EquipmentController : Controller
{
    TLCP_DEVEntities4 db = new TLCP_DEVEntities4();

    (...)

    public ActionResult Edit(int id)         
    {
        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View(db.Equipments.Find(id)); 
    }

    [HttpPost]
    public ActionResult Edit(Equipment equipment)
    {
        if (ModelState.IsValid)
        {
            db.Entry(equipment).State = EntityState.Modified;                    
            db.SaveChanges();     //fails here                                     
            return RedirectToAction("Maintenance"); 
        }

        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View(equipment);
    }

    public ActionResult AddEquipment()
    {
        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View();
    }

    public ActionResult AddEquipment(Equipment equipment)
    {
        try
        {
            db.Equipments.Add(equipment);
            db.SaveChanges();

            return RedirectToAction("Maintenance"); 
        }
        catch (Exception ex)
        {

            ViewData["divisions"] = new SelectList(db.Equipments.
                                    OrderBy(x => x.Division.DivisionName).
                                    Select(x => x.Division).ToList().
                                    Distinct(), "DivisionId", "DivisionName");

            ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

            return View();
        }
    }

    (...)
}

在视图中,我有这些属性的下拉列表,这些属性填充了数据库中已有的可能选项(存储在上面的 ViewData 中)。我尝试了几种不同的方式将这些数据存储到我的模型中,但这种方式似乎效果最好:

<%: Html.DropDownListFor(model => model.DivisionId,
       ViewData["divisions"] as SelectList, "")%>

好的,经过大量调试,问题似乎是因为延迟加载的属性具有空属性,这些属性在它们的表中是不允许的。我的示例将更多地处理创建新设备对象,尽管我相信编辑它们的问题是相同的。

Division 示例:因此 Equipment 类中的 DivisionId 可以为 null (用户不知道或设备不属于特定部门), Equipment 表/类不会抱怨这一点。但是当我尝试 SaveChanges() 时,程序会抱怨,因为虚拟 Division 对象为空(默认 DivisionId 为 0,DivisionName 为空)。由于 Equipment.DivisionId 为空,我不想更新此 Equipment 对象的 Division 表。有没有办法解决这个问题?我不应该延迟加载吗?

PAU 示例:由于 PAUId 是所有设备对象的必需属性,但与除法示例中一样,PAU.PAUNumber 和 PAU.PAUDescription 为空(并且 PAU.PAUId 为默认值 0)导致错误。这就像第一个一样,但具有 required 属性(所以我不确定它是否需要以不同方式处理)。

所以我不确定如何解决这个问题。

  • 是否延迟加载问题,因为如果 Id/外键不为空,我只想将设备对象连接到其他表?

  • 我可以调用一些方法来根据 Id 从其他表中更新设备对象的值吗?这是我需要自己创建的方法吗?

  • 如果我摆脱延迟加载,您能解释一下我应该如何编写查询,以便我仍然可以访问规范化数据(如 DivisionName)吗?

我为超长的帖子道歉。我只是不想错过任何可能重要的事情。

编辑

我对 PAU 示例有一个粗略的解决方案(但我认为它不适用于除法示例,因为在设备中允许空值但不允许在单个表中使用空值)。

public ActionResult AddEquipment(Equipment equipment)
    {
        try
        {
            equipment.PAU.PAUId = equipment.PAUId;
            equipment.PAU.PAUNumber = db.PAUs.Find(equipment.PAUId).PAUNumber;
            equipment.PAU.PAUDescription = db.PAUs.Find(equipment.PAUId).PAUDescription;


        (...)

    }

虽然它不是很优雅。我试着看一个关于反射的教程,但它并没有真正的意义。如果那将是一个更优雅的解决方案,有人可以尝试解释一下吗?

我仍在寻找除法示例的解决方案(因为 Equipment.DivisionId 可以为空,但 Division.DivisionId 不能为空,这不起作用),因此任何关于此或更优雅的解决方案的帮助都会很大赞赏!

4

1 回答 1

0

我的代码的另一部分表现得很奇怪,导致了错误。感谢您的帮助!谢谢!

于 2012-06-26T18:10:21.413 回答