What is the best way to preserve the original properties of an object if they are not included in the MVC binding from the edit page?

I have an ASP.NET MVC view for editing a model object. The editing page includes most of the properties of my object, but not all of them - in particular, it does not include the CreateOn and CreatedBy fields, since they are configured to be created (at my service level) and should not change in the future.

If I do not include these properties in hidden fields, they will not be selected during the binding and will not be available when I save the modified object in my EF 4 DB context. In fact, after saving, the original values ​​will be overwritten with zeros (or some standard defaults).

I do not want to throw them in hidden fields, because it is a waste of bytes, and I do not want these values ​​to undergo potential manipulation.

Is there a first-class way to handle this situation? Is it possible to specify the EF Model property, should be ignored if not explicitly set?

+1
asp.net-mvc entity-framework
Nov 16 '11 at 1:45
source share
5 answers

Use either:

public bool SaveRecording(Recording recording) { // Load only the DateTime property, not the full entity DateTime oldCreatedOn = db.Recordings .Where(r => r.Id == recording.Id) .Select(r => r.CreatedOn) .SingleOrDefault(); recording.CreatedOn = oldCreatedOn; db.Entry(recording).State = EntityState.Modified; db.SaveChanges(); return true; } 

( Edit: The query loads the CreatedOn column from the database and is therefore cheaper and faster than loading the full object. Since you only needed the CreatedOn property, using Find would be an extra overhead: you load all the properties, but you need only one of them. Except Facebook, loading a complete object using Find and then detaching it later can be a shortcut using AsNoTracking : db.Recordings.AsNoTracking().SingleOrDefault(r => r.Id == recording.Id); This loads the object without connecting it , so you don’t need to detach the object. Using AsNoTracking t Also speeds up the loading of the object.)

Edit 2

If you want to load more than one property from the database, you can create an anonymous type:

 public bool SaveRecording(Recording recording) { // Load only the needed properties, not the full entity var originalData = db.Recordings .Where(r => r.Id == recording.Id) .Select(r => new { CreatedOn = r.CreatedOn, CreatedBy = r.CreatedBy // perhaps more fields... }) .SingleOrDefault(); recording.CreatedOn = originalData.CreatedOn; recording.CreatedBy = originalData.CreatedBy; // perhaps more... db.Entry(recording).State = EntityState.Modified; db.SaveChanges(); return true; } 

(End of editing 2)

Or:

 public bool SaveRecording(Recording recording) { Recording oldVersion = db.Recordings.Find(recording.Id); recording.CreatedOn = oldVersion.CreatedOn; // flag only properties as modified which did really change db.Entry(oldVersion).CurrentValues.SetValues(recording); db.SaveChanges(); return true; } 

( Edit: Using CurrentValues.SetValues contains only properties with a changed name that really have changed from the original state in the database. When you call SaveChanges , EF sends only the properties marked as changed in the UPDATE statement to the database. At that time how setting a state in Modified means that all properties are changed, regardless of whether they really have changed or not. The UPDATE statement will be more expensive since it contains an update for all columns.)

+3
Nov 16 '11 at 4:00 p.m.
source share

If you do not want to send this data to the client, I see no other option than to load the original from db at the service level, when you save and merge these original property values ​​back to the updated object. EF does not know that you did not set these values ​​to zero and in fact do not want to store them that way.

0
Nov 16 '11 at 3:22
source share

You can implement your own middleware that ignores properties that you do not want to transfer. Start here - http://lostechies.com/jimmybogard/2009/03/18/a-better-model-binder/

0
Nov 16 '11 at 3:26
source share

I think that when you are going to update, use getById to get the whole entity, and then set the appropriate properties, and then you can update. It will be easy if you use some kind of mapper ( Automapper ) to map your properties from the view model to the loaded object from the database.

0
Nov 16
source share

If you want to avoid additional (unnecessary) calling your database before each update, you can use self-monitoring objects or set StoreGeneratedPattern="Identity" for these fields in your entity model. And yes, Identity is misleading, but it seems like the setup you want:

Identification The value is generated upon insertion and remains unchanged upon update.

http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.storegeneratedpattern.aspx

0
Nov 16 2018-11-11T00:
source share



All Articles