为什么调用saveChanges()会抛出错误“对象引用未设置为对象的实例”。

时间:2015-12-28 11:18:22

标签: asp.net-mvc-4

我有以下代码供查看:

@model test1.Models.CustomerVM

@{
    ViewBag.Title = "Create";
}
<link href="~/Content/themes/base/jquery.ui.all.css" rel="stylesheet" />
<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Customer</legend>

        @Html.HiddenFor(model=>model.UserId)
        @Html.HiddenFor(model=>model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.User)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User)
            @Html.ValidationMessageFor(model => model.User)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Password)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.Password)
            @Html.ValidationMessageFor(model => model.Password)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ConfirmPassword)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(model => model.ConfirmPassword)
            @Html.ValidationMessageFor(model => model.ConfirmPassword)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.NameTitle)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.NameTitle, Model.NameTitleColl)
            @Html.ValidationMessageFor(model => model.NameTitle)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.FName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FName)
            @Html.ValidationMessageFor(model => model.FName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.LName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LName)
            @Html.ValidationMessageFor(model => model.LName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Gender)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.Gender, Model.GenderColl)
            @Html.ValidationMessageFor(model => model.Gender)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.DOB)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.DOB)
            @Html.ValidationMessageFor(model => model.DOB)
        </div>

        @* contacts *@
             <div class="editor-label">
            @Html.LabelFor(model => model.AddressL1)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AddressL1)
            @Html.ValidationMessageFor(model => model.AddressL1)
        </div>

             <div class="editor-label">
            @Html.LabelFor(model => model.AddressL2)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AddressL2)
            @Html.ValidationMessageFor(model => model.AddressL2)
        </div>

             <div class="editor-label">
            @Html.LabelFor(model => model.Suburb)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Suburb)
            @Html.ValidationMessageFor(model => model.Suburb)
        </div>

             <div class="editor-label">
            @Html.LabelFor(model => model.Country)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Country)
            @Html.ValidationMessageFor(model => model.Country)
        </div>

             <div class="editor-label">
            @Html.LabelFor(model => model.Phone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Phone)
            @Html.ValidationMessageFor(model => model.Phone)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {

    <script src="~/Scripts/jquery-2.1.4.min.js"></script>
    <script src="~/Scripts/jquery-ui-1.11.4.min.js"></script>

    @Scripts.Render("~/bundles/jqueryval")

    <script>
        $(document).ready(function () {
            $('#DOB').datepicker({
                appendText: 'mm/dd/yyyy',
                showOn: 'both',
                buttonText: 'click me',
                dateFormat: 'mm/dd/yy',
                changeMonth: 'true',
                changeYear: 'true',
                yearRange: '1900:2016'
            });
        });
    </script>

}

视图工作正常显示数据应该是。但是当我单击Create以保存记录时,将抛出以下错误:对象引用未设置为对象的实例执行db.SaveChanges()行时抛出

以下是执行保存的操作。 注意:虽然视图有更多字段,但我没有保存所有仅我在Create()中声明的那些将保存a.k.a只保存mst_users中的数据

    [HttpPost]
    public ActionResult Create(CustomerVM custObject)
    {

            if (ModelState.IsValid)
            {
                mst_users user = new mst_users 
                { 
                    uName=custObject.User, 
                    password=custObject.Password, 
                    dtCreated=DateTime.UtcNow, 
                    isLocked=false
                };

                db.mst_users.Add(user);
                db.SaveChanges();
         }
   }

当我检查接收数据到方法时,它具有执行保存所需的所有数据,但有趣的是当它抛出异常时,调试器将控制权移到view并指向{{ 1}}字段。

NameTitle

这是映射到实体类mst_users

的表
Line 44:         </div>
Line 45:         <div class="editor-field">
Line 46:             @Html.DropDownListFor(model => model.NameTitle, Model.NameTitleColl)
Line 47:             @Html.ValidationMessageFor(model => model.NameTitle)
Line 48:         </div>

这是实体类:

enter image description here

here is the video

Here is a null reference error video

3 个答案:

答案 0 :(得分:1)

正如你所说:

  

但有趣的是,当它抛出异常时,调试器将控件带到视图并指向NameTitle字段。

问题不完全在SaveChanges(),但是当您的操作成功执行并再次呈现相同的创建视图时,实际会发生异常。这一次,您的ModelModel.NameTitleCollnull

当您调用Create操作时,您必须填充CustomerVM方法并将其返回查看。但是,在对Create方法进行POST呼叫后,如果要再次渲染相同的视图,则必须再次填充CustomerVM,并将其传递给视图。类似的东西:

[HttpPost]
public ActionResult Create(CustomerVM custObject)
{

        if (ModelState.IsValid)
        {
            mst_users user = new mst_users 
            { 
                uName=custObject.User, 
                password=custObject.Password, 
                dtCreated=DateTime.UtcNow, 
                isLocked=false
            };

            db.mst_users.Add(user);
            db.SaveChanges();
     }

    return View(custObject);
    //or return View(new CustomerVM()) just to make you understand

}

更新: (根据您附加的视频)

您只填充User模型的PasswordConfirmPasswordCustomerVM字段。您已使用Address属性修饰了Fname*[Required]*和其他几个属性。这意味着,发布时不得null(为了使模型有效)。否则,您的模型状态将无效。您可以在视频中清楚地看到,custObject包含所需值的null。完全符合预期,ModelState.IsValid会给你false作为回报。

更新: (基于您附加的第二个视频) 你是对的,你的例外发生在db.SaveChanges()行。您的调试器带您进行查看的原因在于您的操作中的一段代码:

try
{
   ....
   db.SaveChanges();
 }
 catch()
 {
   return View(); // <- this line
 }

从技术上讲,会发生异常,并且程序的控制权会移动到catch块。然后执行return View()以处理异常,并在呈现视图时,Model.NameTitleColl为空。这引发了另一个异常,你实际看到了。然而,你已经跳过了orignal例外。

原因和解决方案:

从您的代码中,我可以看到,您没有在操作中初始化db对象,这会抛出orignal异常。在对其执行任何操作之前,请初始化db对象。你可以这样做:

db = new YourDbContextNameHere(); //initialize your db object with your Dbcontext class constructor

然后执行:

db.mst_users.Add(user);
db.SaveChanges();

它会以这种方式正常工作。

答案 1 :(得分:0)

db db.mst_users 会抛出 NullPointerException ?在我看来,其中任何一个都没有得到适当的实例化。

答案 2 :(得分:0)

根据@Zeeshan的回答,我假设您第一次点击创建按钮时, mst_users 会保存到数据库中。问题可能是您返回相同的视图而没有传递包含用于填充下拉列表的Model.NameTitleColl的相应模型。因此,NullExpception

更新1 您的模型将无效,因为CustomerVM中的大部分必填字段均为空。

例如 以下必填字段 LNameFName等都为空。在您的视频中,视图中未提供此值。