title: EntityFramework storing sensitive data
body: <p>Say on one of your entities you have a property that when you need saved to the database, it needs to be encrypted but when you're dealing with it in code, you just want to treat is as plain text.</p>
  
  <p>Right now, I have this setup:</p>
  
  <pre><code>public class MyEntity 
  {
     [SecureStringAttribute]
     public string SecureString {get;set;}
  }
  </code></pre>
  
  <p>My DbContext, this is where the "magic" happens.</p>
  
  <pre><code>public MyDbContext()
      : base("conn")
  {
      ((IObjectContextAdapter)this).ObjectContext.SavingChanges += ObjectContextOnSavingChanges;
      ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContextOnObjectMaterialized;
  }
  
  private void ObjectContextOnObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
  {
      DecryptSecureString(e.Entity);
  }
  
  private void ObjectContextOnSavingChanges(object sender, EventArgs e)
  {
      EncryptSecureStrings(sender as ObjectContext);
  }
  
  private void DecryptSecureString(object entity)
  {
      if (entity != null)
      {
          foreach (
              PropertyInfo propertyInfo in
                  EntityFrameworkSecureStringAttribute.GetSecureStringProperties(entity.GetType()))
          {
              string encryptedValue = propertyInfo.GetValue(entity) as string;
              if (!string.IsNullOrEmpty(encryptedValue))
              {
                  string decryptedValue = EncDec.Decrypt(encryptedValue);
                  propertyInfo.SetValue(entity, decryptedValue);
              }
          }
      }
  }
  
  private void EncryptSecureStrings(ObjectContext context)
  {
  
      if (context != null)
      {
          foreach (ObjectStateEntry objectStateEntry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Where(x =&gt; x.Entity != null))
          {
  
              object[] data = new object[objectStateEntry.CurrentValues.FieldCount];
              objectStateEntry.CurrentValues.GetValues(data);
  
              PropertyInfo[] properties =
                  EntityFrameworkSecureStringAttribute.GetSecureStringProperties(objectStateEntry.Entity.GetType());
  
              foreach (PropertyInfo propertyInfo in properties)
              {
                  string currentValue = objectStateEntry.CurrentValues[propertyInfo.Name] as string;
                  if (!string.IsNullOrEmpty(currentValue))
                  {
                      int index = objectStateEntry.CurrentValues.GetOrdinal(propertyInfo.Name);
                      string newVal = EncDec.Encrypt(currentValue);
                      objectStateEntry.CurrentValues.SetValue(index, newVal);
  
                  }
              }
  
          }
      }
  }
  </code></pre>
  
  <p>It's straight forward I just encrypt/decrypt the string on save and on load. However if I do the following:  </p>
  
  <pre><code>MyEntity entity = new MyEntity(){SecureString= "This is secret!!"};
  dbContext.SaveChanges();
  </code></pre>
  
  <p>At this point <code>entity.SecureString</code> has been encrypted and any further use with this object will be incorrect.</p>