简体   繁体   中英

Entity Framework 6 Update where foreign key references NULL

I have a table DivorceCases which has many fields and it's model is like:

    [Key]
    [Required]
    public string case_id { get; set; }
    public string user_id { get; set; }
    public DateTime case_date { get; set; }
    public virtual Transactions t { get; set; }

I am trying to add transaction details to an existing row but I am getting a [NullReferenceException: Object reference not set to an instance of an object.] error. In the DivorceCases table EF6 has created a column t_id for foreign key reference of Transactions Table.

离婚案件表快照

I used :

public static void UpdatePayment(string cid,string txnno)
  {
 DivorceCasesContext db = new DivorceCasesContext();
            DivorceCases dc = db.DivorceCase.Where(x => x.case_id == cid).Include(x => x.t).SingleOrDefault();
            if (dc.t == null || dc.t.txn_id1 == null || dc.t.txn_id1 == "")
            {
                dc.t.txn_id1 = txnno;
                dc.t.amount1 = amount.ToString();
                dc.t.date1 = DateTime.Now.ToString();
            }
            else
            {
                dc.t.txn_id2 = txnno;
                dc.t.amount2 = amount.ToString();
                dc.t.date2 = DateTime.Now.ToString();
            }
            db.Set<DivorceCases>().Attach(dc);
            db.Entry(dc).State = EntityState.Modified;
            db.SaveChanges();
        }
}

The Error I'm getting is:

    [NullReferenceException: Object reference not set to an instance of an object.]
   gonylaw.Helpers.Amounts.UpdatePayment(String cid, String txnno) +425
   gonylaw.Controllers.PaymentController.PaymentProcessor(CreditCard c) +461
   lambda_method(Closure , ControllerBase , Object[] ) +104
   System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +14
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +157
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
   System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
   System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9644037
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

You are accessing properties of dc.t without ensuring dc.t is not null. If the if statement short circuits on the first condition, dc.t is null, yet you attempt to assign a value to dc.t.txn_id :

if( dc.t == null || ... )
{
    dc.t.txn_id1 = txnno; // null ref exception here
}

Asside from that, there are other improvements I suggest:

public static void UpdatePayment(string cid,string txnno)
{
    // add using block to dispose of DbContext after you're done with it
    using( DivorceCasesContext db = new DivorceCasesContext() )
    {
        DivorceCases dc = db.DivorceCase.Include(x => x.t)
            .Where( x => x.case_id == cid )
            .SingleOrDefault();

            // take care of your null ref problem
            if( dc.t == null )
            {
                dc.t = new Transactions();
            }

            // simplify null/empty string check
            if( string.IsNullOrEmpty( dc.t.txn_id1 ) )
            {
                dc.t.txn_id1 = txnno;
                dc.t.amount1 = amount.ToString();
                dc.t.date1 = DateTime.Now.ToString();
            }
            else
            {
                dc.t.txn_id2 = txnno;
                dc.t.amount2 = amount.ToString();
                dc.t.date2 = DateTime.Now.ToString();
            }

            // this is not needed - dc is already attached to the context
            //  (unless you're doing something nonstandard by default
            //   within your DbContext)
            //db.Set<DivorceCases>().Attach(dc);
            //db.Entry(dc).State = EntityState.Modified;

            db.SaveChanges();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM