c# - 数据库验证错误。在一个表中允许空值,但在相关(规范化)表中不允许空值

标签 c# asp.net-mvc entity-framework nullable

我已经找了两天的答案了。我甚至不知道到底出了什么问题,但我想我可能已经找到了可能的罪魁祸首。
我的程序是一个数据库跟踪器/管理器,可以跟踪我公司的设备。用户可以查询、创建和编辑设备。现在,查询数据库是可行的,但是当我试图添加或更新数据库时,程序会抛出验证错误(我将在下面详细介绍)。
我有一个设备类,它有许多可以为空的属性(因为用户在创建一个新条目时可能不知道这些属性中的许多,所以我们几乎所有的属性都为空),并且连接到(使用外键和延迟加载/“virtual”)其他一些表,这些表是为了帮助规范化数据库而创建的。
以下是一些删节的代码以帮助您:
设备型号:

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以及相关的描述和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, "")%>

好的,所以经过大量调试后,问题似乎是因为延迟加载的属性具有空属性,而这些属性在它们的表中是不允许的。我的示例将更多地处理创建新设备对象的问题,尽管我相信编辑它们的问题是相同的。
分区示例:
所以设备类中的divisionid可以为空(用户不知道或者设备不属于特定的分区),设备表/类不会对此抱怨。但当我尝试保存changes()时,程序会抱怨,因为虚拟division对象为空(默认divisionid为0,divisionname为空)。由于equipment.divisionid为空,我不想更新此设备对象的division表。有办法绕过这个吗?我不应该偷懒装货吗?
PAU示例:
由于pauid是所有设备对象的必需属性,但与分区示例一样,pau.pauNumber和pau.pauDescription为空(pau.pauid是默认的0),因此会导致错误。这与第一个类似,但具有必需的属性(因此我不确定是否需要以不同的方式处理)。
所以我真的不知道怎么解决这个问题。
由于我只想在id/外键不为空的情况下将我的设备对象连接到其他表,所以延迟加载问题吗?
我是否可以调用一些方法来根据id从其他表中更新设备对象的值?这是一种我需要创造自己的方法吗?
如果我摆脱了延迟加载,您能解释一下我应该如何编写查询,以便仍然可以访问规范化数据(比如divisionname)吗?
我为这封超长的信道歉。我只是不想错过任何重要的事情。
编辑
我对pau示例有一个粗略的解决方案(但我认为它不适用于division示例,因为它允许设备内的空值,而不允许单独的表)。
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不可以为空,这不起作用),因此在此方面的任何帮助或更优雅的上述解决方案将不胜感激!

最佳答案

我的代码的另一部分有点奇怪,这导致了错误。谢谢你的帮助!谢谢!

关于c# - 数据库验证错误。在一个表中允许空值,但在相关(规范化)表中不允许空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11192226/

相关文章:

c# - "Column names in each table must be unique."数据库更新期间

c# - 我是否需要序列化抽象基类以使派生类可序列化

c# - 库中的异常处理策略

c# - 在 Razor View 中使用 Partials 的性能成本

asp.net-mvc - 使用 https ASP.NET MVC 网站保护所有资源(图像、脚本、页面、sessionCookie),并从 http 重定向到 https

c# - 在 Entity Framework 中使用 DbSet<TEntity>.Local 属性

c# - 发布时未调用带有 Telerik Kendo Grid Read 方法 ([DataSourceRequest]) 的 ASP.NET Core 2.0

asp.net-mvc - OWIN认证中间件 : logging off

c# - 实体被移动而不是添加

c# - 从 SQL-Server 导出/导入数据子集