EF ObjectStateManager.GetObjectStateEntries (plural)

I’ve been using the GetObjectStateEntry method for a while so that I can view and interact with the state of a particular entity that I have in hand.

Today I used the plural version of this method for the first time and boy do I like it!

GetObjectStateEntries takes as a parameter an EntityState enum: Added, Modified, Deleted, Unchanged or Detached.

It provides a perfect opportunity to do some work on entities prior to hitting the datastore during a save changes event.

For example, if you have an entity with a property to track the modification date you could update that property any time any other property in the entity is changed which might be wasteful. But with the GetObjectStateEntries method, I am able to just update the Modified Date property on all changed objects at once just before I save changes.

Here’s some code for dealing with the Customer entity that is derived directly from the customer table in the AdventureWorks database.

Now, this poses an architectural question and you may want to put this particular business logic elsewhere, but it’s merely a demonstration of what you can do with this method.

Because the generated classes are partial classes, I just create another partial class for my AdventureWorksLTEntities class and intercept the SaveChanges method. Then I grab all of the modified objects, use the Entity property to filter just Customers, then changed the Modified Date property. Next I grab the Added objects, change the Modified Date and also add in a default password hash and password salt. These are required for customer rows. (Read more about hashing passwords here on Beth Massi’s blog.)

Namespace AdventureWorksLTModel
  Partial Public Class AdventureWorksLTEntities

    Private Sub AdventureWorksLTEntities_SavingChanges(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SavingChanges
      Dim changedEntities = Me.ObjectStateManager.GetObjectStateEntries(EntityState.Modified)
      For Each stateEntryEntity In changedEntities
        If TypeOf stateEntryEntity.Entity Is Customer Then
          Dim cust As Customer = stateEntryEntity.Entity
          cust.ModifiedDate = Now
        End If
      Dim addedEntities = Me.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
      For Each stateEntryEntity In addedEntities
        If stateEntryEntity.Entity.GetType() Is Customer Then
          Dim cust As Customer = stateEntryEntity.Entity
          cust.ModifiedDate = Now
          ‘password hash cannot be null
          ‘for demo purposes just put a default string in there
          Dim strPassword As String = “p@ssw0rd”
          Dim encoder As New System.Text.UTF8Encoding()
          Dim SHA1Hasher As New Security.Cryptography.SHA1CryptoServiceProvider
          Dim hashedBytes As Byte() = SHA1Hasher.ComputeHash(encoder.GetBytes(strPassword))
          cust.PasswordHash = Convert.ToBase64String(hashedBytes)
          ‘customer table also needs salt for hash
          Dim buffer() As Byte = New Byte(5) {}
          Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()
          cust.PasswordSalt = Convert.ToBase64String(buffer)
        End If
    End Sub

  End Class
End Namespace

I have a feeling that this existed in Beta2, but I have updated both of my boxes and don’t feel like digging into a VPC just to verify.

  Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!  

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.