Search code examples
c#entity-frameworkasp.net-coreabp-framework

Compare two models in ASP.Net Core to detect changes without loop


I'm trying to compare two models, one is the instance that contains the data to be updated, and the other is the instance that has the existing data retrieved from the database using the primary key of the record. I need to create a third instance of another model/Dto as a list and store the details of the updated records in the incoming model in the format: Updated field, old data, new data, and time of updating. is it possible to do this without looping through the data?


Solution

  • Yes I've found out another solution. If you are using Entity Framework, you can use the ChangeTrackerof DbContext to get the details of the entities which were changed recently.

    [HttpPut]
        public List<ChangeLog> UpdateBook(Books input)
        {
            var bookToChange = _context.Books.Find(input.BookId);
            bookToChange.BookName = input.BookName;
            bookToChange.BookPrice = input.BookPrice;
            bookToChange.Author = input.Author;
            _context.Books.Update(bookToChange);
            var changeLog = GetChangeLog();
            return changeLog;
        }
    
        public List<ChangeLog> GetChangeLog()
        {
            List<ChangeLog> changeLog = new List<ChangeLog>();
            var changedEntities = _context.ChangeTracker.Entries().Where(e => e.State == Microsoft.EntityFrameworkCore.EntityState.Modified).ToList();
            changedEntities.ForEach(change => {
                foreach (var prop in change.OriginalValues.Properties)
                {
                    var originalValue = change.OriginalValues[prop].ToString();
                    var updatedValue = change.CurrentValues[prop].ToString();
                    if (originalValue != updatedValue)
                    {
                        var changes = new ChangeLog
                        {
                            Property = prop.Name,
                            oldValue = originalValue,
                            newValue = updatedValue,
                            dateOfChange = DateTime.Now
                        };
                        changeLog.Add(changes);
                    }
                }
            });
    
            return changeLog;
        }
    

    And the Dtos:

    public class Books
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int BookId { get; set; }
        public string BookName { get; set; }
        public double BookPrice { get; set; }
        public string Author { get; set; }
    
    }
    
    public class ChangeLog
    {
        public string Property { get; set; }
        public string oldValue { get; set; }
        public string newValue { get; set; }
        public DateTime dateOfChange { get; set; }
    }