14
var paymentAttempt = _auctionContext.PaymentAttempts.Where(o => o.Id == paymentAttemptId).SingleOrDefault();
if (paymentAttempt != null)
{
    paymentAttempt.PaymentAttemptStatusId = (int)PaymentAttemptStatus.Defunct;
    paymentAttempt.PaymentAttemptStatus = _auctionContext.PaymentAttemptStatuses.Where(pas => pas.Id == paymentAttempt.PaymentAttemptStatusId).First();

    var relevantWinningBidsTotalPrices = _auctionContext.GetWinningBidsTotalPricesForPaymentAttempt(paymentAttemptId).ToArray();

    foreach (var winningBid in relevantWinningBidsTotalPrices)
    {
        winningBid.Locked = false;
        _auctionContext.UpdateObject(winningBid);
    }
    _auctionContext.SaveChanges();
}

In the above code after

_auctionContext.SaveChanges();

is called winningBid is updated as expected but paymentAttempt isn't. Why is this? It is really frustrating. There is no error either. I would expect a failure to occur if there was a problem like EF wasn't tracking the object or something like that, but no such error is happening.

Hannele
  • 9,301
  • 6
  • 48
  • 68
Sachin Kainth
  • 45,256
  • 81
  • 201
  • 304
  • 1
    Use Attach to get your modified entity into context .Before you save. Context had no idea what you are talking about. – Tabish Sarwar Feb 13 '13 at 16:43
  • Maybe it is worth mentioning the differences between add, attach and entry: [entity framework core: difference between add, entry and attach methods/](https://gavilan.blog/2018/12/09/entity-framework-core-difference-between-add-entry-and-attach-methods/) – Matt Mar 29 '22 at 13:20

4 Answers4

21

That's because you need to pass the paymentAttempt object to your context, to let it know that it is an object that needs to be updated.

For example, assuming that _auctionContext is an instance of DbContext:

// any changes related to the paymentAttempt object 

_auctionContext.Entry(paymentAttempt).State = EntityState.Modified;

foreach (var winningBid in relevantWinningBidsTotalPrices)
{
   winningBid.Locked = false;
   _auctionContext.UpdateObject(winningBid);
}

_auctionContext.SaveChanges();

Another option is the Attach method:

_auctionContext.Attach(paymentAttempt);
_auctionContext.ObjectStateManager.ChangeObjectState(paymentAttempt, System.Data.EntityState.Modified);
Hannele
  • 9,301
  • 6
  • 48
  • 68
Jorge
  • 17,896
  • 19
  • 80
  • 126
5

If you don't have Entry try adding:

using System.Data.Entity.Infrastructure;

using System.Data.Entity;

then you may simply use:

_auctionContext.Entry(paymentAttempt).State = EntityState.Modified;
_auctionContext.SaveChanges();
durron597
  • 31,968
  • 17
  • 99
  • 158
borzou27
  • 51
  • 1
  • 2
1

I fell on this question but for a different problem. I discovered that if you call SaveChanges() on an object that hasn't been modified, EF will not update anything. This makes sense, but I needed the DB to be updated so that other users would see that a SaveChanges() had been executed, regardless of whether any fields had changed. To force an update without changing any fields:

    Dim entry As DbEntityEntry = entities.Entry(myentity)
    entry.State = Entity.EntityState.Modified
smirkingman
  • 6,167
  • 4
  • 34
  • 47
1

I know this is late but there's another explanation worth mentioning. Even though your field name contains ID and may be set to autoincrement, be sure to verify that you declared it in your table the primary key.

Missy
  • 1,286
  • 23
  • 52