/// <summary>
 /// Create a list of all available Update methods from a data migration class, indexed by the version number
 /// </summary>
 private static Dictionary <int, MethodInfo> CreateUpgradeLookupTable(IDataMigration dataMigration)
 {
     return(dataMigration
            .GetType()
            .GetMethods(BindingFlags.Public | BindingFlags.Instance)
            .Select(GetUpdateMethod)
            .Where(tuple => tuple != null)
            .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2));
 }
Пример #2
0
        /// <summary>
        /// Returns the UninstallAsync method from a data migration class if it's found
        /// </summary>
        private static MethodInfo GetUninstallAsyncMethod(IDataMigration dataMigration)
        {
            var methodInfo = dataMigration.GetType().GetMethod("UninstallAsync", BindingFlags.Public | BindingFlags.Instance);
            if (methodInfo != null && methodInfo.ReturnType == typeof(Task))
            {
                return methodInfo;
            }

            return null;
        }
Пример #3
0
        /// <summary>
        /// Returns the Create method from a data migration class if it's found
        /// </summary>
        private static MethodInfo GetCreateMethod(IDataMigration dataMigration)
        {
            var methodInfo = dataMigration.GetType().GetMethod("Create", BindingFlags.Public | BindingFlags.Instance);
            if (methodInfo != null && methodInfo.ReturnType == typeof(int))
            {
                return methodInfo;
            }

            return null;
        }
Пример #4
0
        /// <summary>
        /// Returns the Uninstall method from a data migration class if it's found
        /// </summary>
        private static MethodInfo GetUninstallMethod(IDataMigration dataMigration)
        {
            var methodInfo = dataMigration.GetType().GetMethod("Uninstall", BindingFlags.Public | BindingFlags.Instance);

            if (methodInfo != null && methodInfo.ReturnType == typeof(void))
            {
                return(methodInfo);
            }

            return(null);
        }
Пример #5
0
        /// <summary>
        /// Returns the CreateAsync method from a data migration class if it's found
        /// </summary>
        private static MethodInfo GetCreateAsyncMethod(IDataMigration dataMigration)
        {
            var methodInfo = dataMigration.GetType().GetMethod("CreateAsync", BindingFlags.Public | BindingFlags.Instance);

            if (methodInfo != null && methodInfo.ReturnType == typeof(Task <int>))
            {
                return(methodInfo);
            }

            return(null);
        }
        private void PerformMigration(IDataMigration migration, MigrationInfo migrationEntity)
        {
            var migrationType = migration.GetType();

            bool newMigration = false;

            if (migrationEntity == null)
            {
                newMigration = true;
                migrationEntity = new MigrationInfo { MigrationName = migration.GetType().FullName, Version = -1 };
            }

            try
            {
                migrationEntity.Version = PerformMigration(migration, migrationType,
                                                           migrationEntity.Version + 1);

                if (migrationEntity.Version == NoMigrationsFound)
                {
                    return;
                }

                if (newMigration)
                {
                    this.storage.New(migrationEntity);
                }
                else
                {
                    this.storage.Update(migrationEntity);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
Пример #7
0
        public async Task <string> ExecuteAsync(string recipeFileName, IDataMigration migration)
        {
            var featureInfo = _typeFeatureProvider.GetFeatureForDependency(migration.GetType());

            var recipeBasePath   = Path.Combine(featureInfo.Extension.SubPath, "Migrations").Replace('\\', '/');
            var recipeFilePath   = Path.Combine(recipeBasePath, recipeFileName).Replace('\\', '/');
            var recipeFileInfo   = _hostingEnvironment.ContentRootFileProvider.GetFileInfo(recipeFilePath);
            var recipeDescriptor = await _recipeReader.GetRecipeDescriptor(recipeBasePath, recipeFileInfo, _hostingEnvironment.ContentRootFileProvider);

            recipeDescriptor.RequireNewScope = false;

            var executionId = Guid.NewGuid().ToString("n");

            return(await _recipeExecutor.ExecuteAsync(executionId, recipeDescriptor, new object(), CancellationToken.None));
        }
Пример #8
0
        public async Task <string> ExecuteAsync(string recipeFileName, IDataMigration migration)
        {
            var featureInfo = _typeFeatureProvider.GetFeatureForDependency(migration.GetType());

            var recipeBasePath   = Path.Combine(featureInfo.Extension.SubPath, "Migrations").Replace('\\', '/');
            var recipeFilePath   = Path.Combine(recipeBasePath, recipeFileName).Replace('\\', '/');
            var recipeFileInfo   = _hostingEnvironment.ContentRootFileProvider.GetFileInfo(recipeFilePath);
            var recipeDescriptor = await _recipeReader.GetRecipeDescriptor(recipeBasePath, recipeFileInfo, _hostingEnvironment.ContentRootFileProvider);

            recipeDescriptor.RequireNewScope = false;

            var environment = new Dictionary <string, object>();

            await _environmentProviders.OrderBy(x => x.Order).InvokeAsync((provider, env) => provider.PopulateEnvironmentAsync(env), environment, _logger);

            var executionId = Guid.NewGuid().ToString("n");

            return(await _recipeExecutor.ExecuteAsync(executionId, recipeDescriptor, environment, CancellationToken.None));
        }
        /// <summary>
        /// Returns the Uninstall method from a data migration class if it's found
        /// </summary>
        private static MethodInfo GetUninstallMethod(IDataMigration dataMigration) {
            var methodInfo = dataMigration.GetType().GetMethod("Uninstall", BindingFlags.Public | BindingFlags.Instance);
            if (methodInfo != null && methodInfo.ReturnType == typeof(void)) {
                return methodInfo;
            }

            return null;
        }
 /// <summary>
 /// Create a list of all available Update methods from a data migration class, indexed by the version number
 /// </summary>
 private static Dictionary<int, MethodInfo> CreateUpgradeLookupTable(IDataMigration dataMigration) {
     return dataMigration
         .GetType()
         .GetMethods(BindingFlags.Public | BindingFlags.Instance)
         .Select(GetUpdateMethod)
         .Where(tuple => tuple != null)
         .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
 }
 private DataMigrationRecord GetDataMigrationRecord(IDataMigration tempMigration) {
     return _dataMigrationRepository
         .Table
         .FirstOrDefault(dm => dm.DataMigrationClass == tempMigration.GetType().FullName);
 }
 private DataMigrationRecord GetDataMigrationRecord(IDataMigration tempMigration)
 {
     return(_dataMigrationRepository
            .Table
            .FirstOrDefault(dm => dm.DataMigrationClass == tempMigration.GetType().FullName));
 }
Пример #13
0
 private async Task<DataMigration> GetDataMigrationRecordAsync(IDataMigration tempMigration)
 {
     return (await GetDataMigrationRecord()).DataMigrations
         .FirstOrDefault(dm => dm.DataMigrationClass == tempMigration.GetType().FullName);
 }
Пример #14
0
        private async Task UpdateAsync(IDataMigration dataMigration)
        {
            if (_processedMigrations.Contains(dataMigration))
            {
                return;
            }

            var migrationName = dataMigration.GetType().FullName;

            _processedMigrations.Add(dataMigration);
            _logger.LogInformation("Running migration '{MigrationName}'", migrationName);

            // Apply update methods to migration class.

            var schemaBuilder = new SchemaBuilder(_store.Configuration, await _session.BeginTransactionAsync());

            dataMigration.SchemaBuilder = schemaBuilder;

            // Copy the object for the Linq query.
            var tempMigration = dataMigration;

            // Get current version for this migration.
            var dataMigrationRecord = await GetDataMigrationRecordAsync(tempMigration);

            var current = 0;
            var dataMigrationsDocument = await GetOrCreateDataMigrationsDocumentAsync();

            if (dataMigrationRecord != null)
            {
                // Version can be null if a failed create migration has occurred and the data migration record was saved.
                current = dataMigrationRecord.Version ?? current;
            }
            else
            {
                dataMigrationRecord = new DataMigrationRecord {
                    DataMigrationClass = dataMigration.GetType().FullName !
                };

                dataMigrationsDocument.DataMigrations.Add(dataMigrationRecord);
            }

            try
            {
                // Do we need to call Create()?
                if (current == 0)
                {
                    // try to resolve a Create method.
                    var createMethod = GetCreateMethod(dataMigration);

                    if (createMethod != null)
                    {
                        current = (int)createMethod.Invoke(dataMigration, new object[0]) !;
                    }

                    // try to resolve a CreateAsync method.
                    var createAsyncMethod = GetCreateAsyncMethod(dataMigration);

                    if (createAsyncMethod != null)
                    {
                        current = await(Task <int>) createAsyncMethod.Invoke(dataMigration, new object[0]) !;
                    }
                }

                var lookupTable = CreateUpgradeLookupTable(dataMigration);

                while (lookupTable.TryGetValue(current, out var methodInfo))
                {
                    _logger.LogInformation(
                        "Applying migration '{MigrationName}' from version {Version}",
                        migrationName,
                        current);

                    var isAwaitable = methodInfo.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null;

                    current = isAwaitable
                        ? await(Task <int>) methodInfo.Invoke(dataMigration, new object[0]) !
                        : (int)methodInfo.Invoke(dataMigration, new object[0]) !;
                }

                // If current is 0, it means no upgrade/create method was found or succeeded.
                if (current == 0)
                {
                    return;
                }

                dataMigrationRecord.Version = current;
            }
            catch (Exception ex)
            {
                _logger.LogError(
                    ex,
                    "Error while running migration version {Version} for '{MigrationName}'",
                    current,
                    migrationName);
            }
            finally
            {
                // Persist data migrations
                _session.Save(dataMigrationsDocument);
            }
        }
Пример #15
0
 private async Task <DataMigration> GetDataMigrationRecordAsync(IDataMigration tempMigration)
 {
     return((await GetDataMigrationRecord()).DataMigrations
            .FirstOrDefault(dm => dm.DataMigrationClass == tempMigration.GetType().FullName));
 }
Пример #16
0
 private Tables.OrmTablesInfo GetDataMigrationRecord(IDataMigration tempMigration)
 {
     return(OrmManager.Read <Tables.OrmTablesInfo>(" DataMigrationClass='" + tempMigration.GetType().FullName + "'").FirstOrDefault());
 }