Proximo
Proximo

Reputation: 6541

MVC5 Custom View Model, Get Changes, Update Database

I have a complex object that I've broken down to a ViewModel for form. I'll illustrate a sample of the structure but the number of fields are around 60 total from about 6 different entities intermingled.

//ViewModel

public class SomeViewModel
{
   public TabOne TabOne {get;set;}
   public TabTwo TabTwo {get;set;}

   public SomeViewModel(ComplexObject co)
   {
      this.TabOne = new TabOne { Name = co.Name, Value = co.Value};
      this.TabTwo = new TabTwo { Name = co.Name, Another = co.Another };
   }
}

All this works fine and I get to the Controller from the View

//Controller

[HttpPost]
public ActionResult Update(SomeViewModel vm)
{
     //TODO: 1. Know which properties in the ViewModel changed for auditing

     //TODO: 2. Update all changed EF entities in the database. 

}
  1. Before sending the ViewModel to the View I cache the original Value in a Session object and use reflection to compare the two. It's drawn out and I'll have to do a ton of work for any changes. Is there a better way??

  2. The ViewModel is different structure from the EF Models, so it's a bunch of custom mapping that will need to be done to Update the correct entities. I'd like to avoid that because of the number of fields. Is there a better way?

Upvotes: 1

Views: 882

Answers (1)

Alan Macgowan
Alan Macgowan

Reputation: 481

Ok, not sure if this is what you need but for what I understood:

  1. You can get the original and current values like this:

     using (var dbCtx = new YourDBEntities())
     {
        var yourEntity = dbCtx.YourEntity.Find(1);
    
        var entry = dbCtx.Entry(yourEntity);
    
        foreach (var propertyName in entry.CurrentValues.PropertyNames )
        {
           Console.WriteLine("Property Name: {0}", propertyName);
    
           var originalVal = entry.OriginalValues[propertyName];
           Console.WriteLine("Original Value: {0}", originalVal);
    
           var currentVal = entry.CurrentValues[propertyName];
           Console.WriteLine("Current Value: {0}", currentVal);
        }
     }
    
  2. For mapping ViewModels to your EF Models you can use Automapper, it can be as easy as:

    AutoMapper.Mapper.CreateMap<Book, BookViewModel>();
    var model = AutoMapper.Mapper.Map<BookViewModel>(book);
    

Edit: Ok, if you need to do it manually, you can use the following method for mapping objects:

    public static void MapObjects( object source,  object destiny)
    {
        var modelPropertiesName = new HashSet<string>(source.GetType().GetProperties().Select(x => x.Name));
        var entityProperties = destiny.GetType().GetProperties();

        var propertyList = entityProperties.Where(p => modelPropertiesName.Contains(p.Name))
                       .ToList();

        foreach (var prop in propertyList)
        {
            var modelProperty = source.GetType().GetProperty(prop.Name);
            var value = modelProperty.GetValue(source);

            prop.SetValue(destiny, value, null);
        }
    }

You just need to pass a destiny object and a source from where to map the properties.

Upvotes: 1

Related Questions