Question

I am using subsonic to access my DB in a mvc application. When trying to update a record using the mvc model binding the record does not update because non of the columns are marked as dirty.

I tried manually marking all the columns as dirty by tweaking the subsonic code, but sometimes i only want to update some of the properties so i do not want to mark them all as dirty.

What is the best way about to do this?

this is my action:

        [HttpPost]
        public ActionResult Update(mapping m)
        {
           m.SetIsNew(false);
           m.Update(true); // here i tweaked the subsonic code passing true sets all the columns to be dirty and updates the record even though isLoaded=false
           return RedirectToAction("New");
        }

this is how i tweaked the subsonic code:

public void Update(IDataProvider provider, Boolean forceUpdate){
            if(this._dirtyColumns.Count>0 || forceUpdate){
                if(forceUpdate)
                    this._dirtyColumns = this.Columns.ToList();
                _repo.Update(this,provider);
                _dirtyColumns.Clear();    
            }
            OnSaved();
       }

EDIT:

I tried out this code to see where the problem lies:

var m = new mapping { ID = 2, Name = "33" };
m.SetIsNew(false);
m.Save();

This too does not work the columns are not set to dirty. It seems that when the an object initializer is used the setters do not get called so the columns are not set to dirty.

I would assume that the default mvc.net model binding works this way and that is why the record is not being updated.

Edit 2

My first edit is wrong as @dyork12 pointed out. Subsonic uses a 'isLoaded' flag, when it is set to false setting properties does not set them as dirty. this is used by subsonic when loading a record, to make sure setting properties while loading does not set then as dirty.

But my question remains what is the best workaround for editing a subsonic object from an mvc.net view using the automatic model binding.

Was it helpful?

Solution

So the original problem (as now understood) is that MVC somehow loads rows and creates DAL objects for them without setting the isLoaded flag, and then any calls to setters do not get added into the dirtyColumns list. You have to find a way to set isLoaded after the record is loaded and the DAL object is created, before any setters are called.

Sorry, I don't know MVC well enough to help, and you didn't include any code for that part. I would expect to insert some kind of event, or inherit from something, or modify a template, or something. As soon as you find a way to set isLoaded, you will solve the problem. I hope.

OTHER TIPS

I'll take a punt and say I think the answer is that _isLoaded is false. Without seeing a lot more code I can't tell you why.

If you create a new record, _isNew is true and _isLoaded is false. When you save it does an INSERT and ignores dirty columns.

If you load an existing record _IsNew is false and _isLoaded is true. When you save it does an UPDATE and only updates dirty columns.

Your code fragment sets _isNew false but does not set _isLoaded true. The columns are not marked dirty, so nothing saves. This is easy to see by reading the ActiveRecord generated code.

[BTW You're wrong about setters -- they are called by an object initialiser.]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top