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
Next
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()
rng.GetBytes(buffer)
cust.PasswordSalt = Convert.ToBase64String(buffer)
End If
Next
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!