johnstaveley
johnstaveley

Reputation: 1499

BreezeJS always returns Store update, insert, or delete statement affected an unexpected number of rows on savechanges

I am trying to update a BreezeJS entity when I adjust a single property and nothing else (I am not doing a delete). I receive the following error message:

{"$id":"1","$type":"System.Web.Http.HttpError, System.Web.Http","Message":"An error has occurred.","ExceptionMessage":"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.","ExceptionType":"System.Data.Entity.Infrastructure.DbUpdateConcurrencyException","StackTrace":" at System.Data.Entity.Internal.InternalContext.SaveChanges()\r\n at Breeze.ContextProvider.EF6.EFContextProvider`1.SaveChangesCore(SaveWorkState saveWorkState)\r\n at Breeze.ContextProvider.ContextProvider.OpenAndSave(SaveWorkState saveWorkState)\r\n at Breeze.ContextProvider.ContextProvider.SaveChanges(JObject saveBundle, TransactionSettings transactionSettings)\r\n at Toriga.Prototype.Html5Portal.Controllers.DataController.SaveChanges(JObject saveBundle) in

I am told this is a concurrency exception but I am always the only user of the database so it can't be. I've checked the primary key of the data object returned has the correct primary key.

My breeze controller:

    readonly EFContextProvider<Context> _contextProvider = new EFContextProvider<Context>();

    public DataController(IUserManager userManager) : base(userManager) { }

    // ~/breeze/Data/Metadata
    [HttpGet]
    public string Metadata()
    {
        return _contextProvider.Metadata();
    }

    // ~/breeze/Data/Jobs
    [HttpGet]
    public async Task<IQueryable<Work>> Jobs()
    {

        var currentUser = await UserManager.FindById(Guid.Parse(User.Identity.GetUserId()));
        var companyId = currentUser.CompanyId.Value;
        return _contextProvider.Context.WorkFolder.Where(w => w.CompanyId == companyId).SelectMany(i => i.Works).Where(j => j.IsDeleted == false);

    }

The (much abreviated) process we are using client side is to initially 'synch' the data, store locally and update any changes later.

Firstlyt, load data and store in local storage:

  var jobsQuery = new breeze.EntityQuery.from("Jobs");
  em.fetchMetadata().then(function () {
  em.executeQuery(jobsQuery).then(function (data) {
     _jobs = data.results;
     var emCache = em.exportEntities();
     store.setItem("EmCache", emCache);
     }, function (data) {
        deferred.reject(data); // passes back unsuccessful
     });
     }, function (data) {
        console.log(data);
        deferred.reject(data); // passes back unsuccessful
  });

then when they press synch later we issue:

                em.saveChanges().then(function () {
                    deferred.resolve();
                }, function (error) {
                    // fail promise
                    console.log(error);
                    deferred.reject(error.message); 
                });

where we always get the error above. The data model is quite complex, though the change I am making is trivial. Apologies the code sample is brief but its from a much larger project with many dependencies. I've unpicked the main points. Any help or clues on where to look as to why this is happening would be appreciated, there doesn't seem to be much out there on this subject.

Upvotes: 0

Views: 607

Answers (2)

johnstaveley
johnstaveley

Reputation: 1499

it turns out that I had a rowversion field which the DBA had helpfully put in, this was updating the record with every change. Once I removed this, all was well again

Upvotes: 1

Jay Traband
Jay Traband

Reputation: 17052

I would start by removing the concurrency check on your database and see if the error goes away.

If it does, and my guess is that it will, then the problem is likely either

  • that you have an 'old' concurrency value in your exported and reimported entities. ( providing I am understanding your question properly) or
  • that you are doing several saves to the same entity is succession and the concurrency value is not being returned to this client properly after the first save. This might occur if you were using the WebApiOData adapter as opposed to the default WebApi adapter.

Upvotes: 0

Related Questions