Closed Eastrall closed 3 years ago
Wouldn't it be simpler to create a MigrationEncryptionProvider
, which takes a source and destination provider - either of which can be null
- and delegates calls to them?
Eg:
public class MigrationEncryptionProvider : IEncryptionProvider
{
public MigrationEncryptionProvider(IEncryptionProvider sourceProvider, IEncryptionProvider destinationProvider)
{
SourceProvider = sourceProvider;
DestinationProvider = destinationProvider;
}
public IEncryptionProvider SourceProvider { get; }
public IEncryptionProvider DestinationProvider { get; }
public string Decrypt(string dataToDecrypt) => SourceProvider is null ? dataToDecrypt : SourceProvider.Decrypt(dataToDecrypt);
public string Encrypt(string dataToEncrypt) => DestinationProvider is null ? dataToEncrypt : DestinationProvider.Encrypt(dataToEncrypt);
}
It's then simply a case of loading the entities in a DbContext
using that provider, marking the encrypted properties as modified, and saving the changes.
public static void Migrate(DbContext context)
{
foreach (var entityType in context.Model.GetEntitiyTypes())
{
var encryptedProperties = entityType.GetProperties().Where(p => ShouldEncrypt(p)).ToList();
if (encryptedProperties.Count == 0) continue;
IQueryable<object> entities = Set(context, entityType.ClrType);
foreach (object entity in entities)
{
var entry = context.Entry(entity);
foreach (var property in encryptedProperties)
{
entry.Property(property.Name).IsModified = true;
}
}
}
context.SaveChanges();
}
This covers all of your current cases, and allows for migrations between other providers as well.
This PR adds a simple data migration mechanism that allows the following migration types:
Before using the
DataMigrator
, please ensure you have a backup of you database. For all migration tools, a database backup should be done before executing any migration operation.Covers issue #7