public void ApplyMigration(string schema, StoreMigration migration)
        {
            int nextIndex = 0;

            try
            {
                // try read version - table maybe doesn't exist
                var lastVersionRecord = _storeDatabaseDriver.Find <MigrationVersionEntity>(schema, VERSION_TABLE, VERSION_ID, migration.Version);

                if (lastVersionRecord.Any())
                {
                    nextIndex = lastVersionRecord.First().NextIndex;
                }
            }
            catch { }

            // skip migrations that already applied;
            var commands = migration.Commands.Skip(nextIndex);

            foreach (var command in commands)
            {
                nextIndex++;

                switch (command.Operation)
                {
                // ToDo: add foreign key constraints
                case MigrationOperation.CreateSchema:
                    _storeDatabaseDriver.CreateSchema(command.SchemaName);
                    _storeDatabaseDriver.CreateTable <MigrationVersionEntity>(schema, VERSION_TABLE);
                    // this operation is not considered as object operation
                    //nextIndex--;
                    break;

                case MigrationOperation.AlterSchemaName:
                    // https://www.sqlservercentral.com/articles/renaming-a-schema-in-sql-server
                    throw new NotImplementedException("SQL Server doesn't support simple schema rename. ");

                case MigrationOperation.CreateTable:
                    _storeDatabaseDriver.CreateTable(command.SchemaName, command.Table);
                    break;

                // V1.0+ migrations
                case MigrationOperation.DeleteTable:
                    _storeDatabaseDriver.DeleteTable(command.SchemaName, command.TableName);
                    break;

                case MigrationOperation.AlterTableName:
                    _storeDatabaseDriver.RenameTable(command.SchemaName, command.TableName, command.NewValue);
                    break;

                case MigrationOperation.AddColumn:
                    _storeDatabaseDriver.AddColumn(command.SchemaName, command.TableName, command.Column);
                    break;

                case MigrationOperation.DeleteColumn:
                    _storeDatabaseDriver.DeleteColumn(command.SchemaName, command.TableName, command.ColumnName, command.Column);
                    break;

                case MigrationOperation.AlterColumnName:
                    _storeDatabaseDriver.RenameColumn(command.SchemaName, command.TableName, command.ColumnName, command.NewValue);
                    break;

                case MigrationOperation.AlterColumn:
                    _storeDatabaseDriver.AlterColumn(command.SchemaName, command.TableName, command.Column);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            // save to version table
            var vesionRecord = new MigrationVersionEntity {
                Applied = DateTime.UtcNow, Version = migration.Version, VersionKey = migration.VersionKey, NextIndex = nextIndex
            };

            var existingRecord = _storeDatabaseDriver.Find <MigrationVersionEntity>(schema, VERSION_TABLE, VERSION_ID, migration.Version);

            if (existingRecord.Any())
            {
                _storeDatabaseDriver.Update(schema, vesionRecord, VERSION_TABLE);
            }
            else
            {
                _storeDatabaseDriver.Insert(schema, vesionRecord, migration.Version, VERSION_TABLE);
            }
        }
 /// <summary>
 /// Find by key
 /// </summary>
 /// <param name="entityType"></param>
 /// <param name="filterColumn"></param>
 /// <param name="value"></param>
 /// <returns></returns>
 public IList Find(Type entityType, string filterColumn, object value)
 {
     ValidateEntityType(entityType);
     return(_db.Find(_schema, entityType, filterColumn, value));
 }