diff --git a/Mongo.Migration/ApplicationLogging.cs b/Mongo.Migration/ApplicationLogging.cs
new file mode 100644
index 0000000..2fbbdba
--- /dev/null
+++ b/Mongo.Migration/ApplicationLogging.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.Logging;
+
+public class ApplicationLogging
+{
+ private static ILoggerFactory _factory = null;
+
+ public static void ConfigureLogger(ILoggerFactory factory)
+ {
+ factory.AddFile("logs/migration/log-migration.log");
+ }
+
+ ///
+ /// Log Factory instance
+ ///
+ public static ILoggerFactory LoggerFactory
+ {
+ get
+ {
+ if (_factory == null)
+ {
+ _factory = new LoggerFactory();
+ ConfigureLogger(_factory);
+ }
+ return _factory;
+ }
+ }
+
+ ///
+ /// Get a ILogger instance to be used in migrations
+ ///
+ /// ILogger instance
+ public static ILogger CreateLogger() => LoggerFactory.CreateLogger("logger");
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Extensions/EnumerableExtensions.cs b/Mongo.Migration/Extensions/EnumerableExtensions.cs
index bae1372..7c70996 100644
--- a/Mongo.Migration/Extensions/EnumerableExtensions.cs
+++ b/Mongo.Migration/Extensions/EnumerableExtensions.cs
@@ -48,5 +48,41 @@ internal static IDictionary> ToMigrationDi
return dictonary;
}
+
+ internal static IEnumerable CheckForDuplicates(this IEnumerable list)
+ {
+ var uniqueHashes = new HashSet();
+ foreach (var element in list)
+ {
+ var version = element.Version.ToString();
+ var typeName = element.GetType().Name;
+
+ if (uniqueHashes.Add(typeName+version))
+ continue;
+
+ throw new DuplicateVersionException(typeName, element.Version);
+ }
+
+ return list;
+ }
+
+ internal static IDictionary> ToMigrationDictionary(
+ this IEnumerable migrations)
+ {
+ var dictonary = new Dictionary>();
+ var types = from m in migrations select m.Type;
+
+ foreach (var type in types)
+ {
+ if (dictonary.ContainsKey(type))
+ continue;
+
+ var uniqueMigrations =
+ migrations.Where(m => m.Type == type).CheckForDuplicates().OrderBy(m => m.Version).ToList();
+ dictonary.Add(type, uniqueMigrations);
+ }
+
+ return dictonary;
+ }
}
}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/AdvancedMigration.cs b/Mongo.Migration/Migrations/AdvancedMigration.cs
new file mode 100644
index 0000000..36064fb
--- /dev/null
+++ b/Mongo.Migration/Migrations/AdvancedMigration.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Migrations
+{
+ public abstract class AdvancedMigration : IAdvancedMigration
+ {
+ protected AdvancedMigration(string version, string collection)
+ {
+ Version = version;
+ CollectionName = collection;
+ }
+
+ public string Version { get; }
+
+ public string CollectionName { get; }
+
+ public Type Type => typeof(AdvancedMigration);
+
+ public virtual void Up(IMongoDatabase db) {
+ var bulk = new List>();
+ var collection = db.GetCollection(CollectionName);
+
+ collection.FindSync(_ => true).ToList().ForEach(document =>
+ {
+ Up(document);
+
+ var update = new ReplaceOneModel(
+ new BsonDocument {{"_id", document["_id"]}},
+ document
+ );
+
+ bulk.Add(update);
+ });
+
+ if (bulk.Count > 0)
+ {
+ collection.BulkWrite(bulk);
+ }
+ }
+
+ public virtual void Down(IMongoDatabase db) {
+ var bulk = new List>();
+ var collection = db.GetCollection(CollectionName);
+
+ collection.FindSync(_ => true).ToList().ForEach(document =>
+ {
+ Down(document);
+
+ var update = new ReplaceOneModel(
+ new BsonDocument {{"_id", document["_id"]}},
+ document
+ );
+
+ bulk.Add(update);
+ });
+
+ if (bulk.Count > 0)
+ {
+ collection.BulkWrite(bulk);
+ }
+ }
+
+ public abstract void Up(BsonDocument document);
+
+ public abstract void Down(BsonDocument document);
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/AdvancedMigrationRunner.cs b/Mongo.Migration/Migrations/AdvancedMigrationRunner.cs
new file mode 100644
index 0000000..06cc6eb
--- /dev/null
+++ b/Mongo.Migration/Migrations/AdvancedMigrationRunner.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Logging;
+using Mongo.Migration.Migrations.Locators;
+using Mongo.Migration.Services;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Migrations
+{
+ internal class AdvancedMigrationRunner : IAdvancedMigrationRunner
+ {
+ private ILogger _logger;
+ public IAdvancedMigrationLocator _migrationLocator { get; }
+
+ private readonly IVersionService _versionService;
+
+ private IMongoDatabase _db;
+
+ private IMongoCollection _migrationshistory;
+
+ public AdvancedMigrationRunner(IAdvancedMigrationLocator migrationLocator, IVersionService versionService)
+ {
+ _migrationLocator = migrationLocator;
+ _versionService = versionService;
+ _logger = ApplicationLogging.CreateLogger();
+ }
+
+ public void Run(IMongoDatabase db, string runningVersion)
+ {
+ _logger.LogInformation($"Starting the migrations ...");
+
+ _db = db;
+ _migrationshistory = db.GetCollection("_migrationshistory");
+
+ var migrations = _migrationLocator.GetMigrations(typeof(AdvancedMigration)) ?? Enumerable.Empty();
+ var migrationsToDowngrade = new List();
+
+ foreach (var migration in migrations)
+ {
+
+ var migrationsInDb = _migrationshistory.FindSync(CreateQueryForMigration(migration.GetType().ToString())).ToList();
+
+ if (migrationsInDb.Count() > 0)
+ {
+ foreach (var document in migrationsInDb)
+ {
+ if (document["productVersion"].ToString().CompareTo(runningVersion) <= 0)
+ continue;
+ else if (document["productVersion"].ToString().CompareTo(runningVersion) > 0)
+ {
+ migrationsToDowngrade.Add(migration);
+ }
+ }
+ }
+ else
+ {
+ if (runningVersion.CompareTo(migration.Version) >= 0)
+ {
+ try
+ {
+ _logger.LogInformation("Starting the migration Up: {0}:{1} ", migration.GetType().ToString(), migration.Version);
+
+ migration.Up(_db);
+ _migrationshistory.InsertOne(new BsonDocument { { "migrationId", migration.GetType().ToString() }, { "productVersion", migration.Version } });
+
+ _logger.LogInformation("Successful migration Up: {0}:{1} ", migration.GetType().ToString(), migration.Version);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error on migration Up {0}:{1} ", migration.GetType().ToString(), migration.Version);
+ }
+ }
+ }
+ }
+
+ migrationsToDowngrade.Reverse();
+ foreach (var migration in migrationsToDowngrade)
+ {
+ try
+ {
+ _logger.LogInformation("Starting the migration Down: {0}:{1} ", migration.GetType().ToString(), migration.Version);
+
+ migration.Down(_db);
+ _migrationshistory.DeleteOne(Builders.Filter.Eq("migrationId", migration.GetType().ToString()));
+
+ _logger.LogInformation("Successful migration Down: {0}:{1} ", migration.GetType().ToString(), migration.Version);
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "Error on migration Down {0}:{1} ", migration.GetType().ToString(), migration.Version);
+ }
+ }
+
+ _logger.LogInformation($"Migrations has been done.");
+ }
+
+ private FilterDefinition CreateQueryForMigration(
+ string type)
+ {
+ return Builders.Filter.Eq("migrationId", type);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/CollectionMigrationRunner.cs b/Mongo.Migration/Migrations/CollectionMigrationRunner.cs
index 8c817bc..9c88bdd 100644
--- a/Mongo.Migration/Migrations/CollectionMigrationRunner.cs
+++ b/Mongo.Migration/Migrations/CollectionMigrationRunner.cs
@@ -14,6 +14,8 @@ internal class CollectionMigrationRunner : ICollectionMigrationRunner
{
private readonly IMongoClient _client;
+ private IMongoDatabase _db;
+
private readonly ICollectionLocator _collectionLocator;
private readonly string _databaseName;
@@ -74,6 +76,7 @@ private CollectionMigrationRunner(
public void RunAll()
{
+ _db = _client.GetDatabase(_databaseName);
var locations = _collectionLocator.GetLocatesOrEmpty();
foreach (var locate in locations)
@@ -83,8 +86,7 @@ public void RunAll()
var databaseName = GetDatabaseOrDefault(information);
var collectionVersion = _versionService.GetCollectionVersion(type);
- var collection = _client.GetDatabase(databaseName)
- .GetCollection(information.Collection);
+ var collection = _db.GetCollection(information.Collection);
var bulk = new List>();
@@ -105,6 +107,7 @@ public void RunAll()
);
bulk.Add(update);
+ //migrationshistory.InsertOne(new BsonDocument {{"migrationId", nameof(type)}, {"productVersion", _runningVersion}});
}
}
}
diff --git a/Mongo.Migration/Migrations/DatabaseMigrationRunner.cs b/Mongo.Migration/Migrations/DatabaseMigrationRunner.cs
new file mode 100644
index 0000000..ec639cc
--- /dev/null
+++ b/Mongo.Migration/Migrations/DatabaseMigrationRunner.cs
@@ -0,0 +1,48 @@
+using Microsoft.Extensions.Options;
+using Mongo.Migration.Startup;
+using Mongo.Migration.Startup.DotNetCore;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Migrations
+{
+ internal class DatabaseMigrationRunner : IDatabaseMigrationRunner
+ {
+ private readonly IMongoClient _client;
+
+ private readonly IAdvancedMigrationRunner _migrationRunner;
+
+ private readonly string _databaseName;
+
+ private readonly string _runningVersion;
+
+ private readonly IOptions _options;
+
+ private const int CONNECTION_CHECK_TIMEOUT = 1000;
+ public DatabaseMigrationRunner(
+ IOptions options,
+ IAdvancedMigrationRunner migrationRunner)
+ : this(
+ new MongoClient(options.Value.ConnectionString),
+ migrationRunner,
+ options.Value.RunningVersion)
+ {
+ _options = options;
+ _databaseName = options.Value.Database;
+ }
+
+ public DatabaseMigrationRunner(
+ IMongoClient client,
+ IAdvancedMigrationRunner migrationRunner,
+ string runningVersion)
+ {
+ _runningVersion = runningVersion;
+ _client = client;
+ _migrationRunner = migrationRunner;
+ }
+
+ public void RunAll()
+ {
+ _migrationRunner.Run(_client.GetDatabase(_databaseName), _runningVersion);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/IAdvancedMigration.cs b/Mongo.Migration/Migrations/IAdvancedMigration.cs
new file mode 100644
index 0000000..8ae0a06
--- /dev/null
+++ b/Mongo.Migration/Migrations/IAdvancedMigration.cs
@@ -0,0 +1,23 @@
+using System;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Migrations
+{
+ public interface IAdvancedMigration
+ {
+ string Version { get; }
+
+ string CollectionName { get; }
+
+ Type Type { get; }
+
+ void Up(IMongoDatabase db);
+
+ void Down(IMongoDatabase db);
+
+ void Up(BsonDocument document);
+
+ void Down(BsonDocument document);
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/IAdvancedMigrationRunner.cs b/Mongo.Migration/Migrations/IAdvancedMigrationRunner.cs
new file mode 100644
index 0000000..6b2a705
--- /dev/null
+++ b/Mongo.Migration/Migrations/IAdvancedMigrationRunner.cs
@@ -0,0 +1,12 @@
+using Mongo.Migration.Migrations.Locators;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Migrations
+{
+ internal interface IAdvancedMigrationRunner
+ {
+ IAdvancedMigrationLocator _migrationLocator { get; }
+
+ void Run(IMongoDatabase db, string runnigVersion);
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/IDatabaseMigrationRunner.cs b/Mongo.Migration/Migrations/IDatabaseMigrationRunner.cs
new file mode 100644
index 0000000..d834c0a
--- /dev/null
+++ b/Mongo.Migration/Migrations/IDatabaseMigrationRunner.cs
@@ -0,0 +1,7 @@
+namespace Mongo.Migration.Migrations
+{
+ internal interface IDatabaseMigrationRunner
+ {
+ void RunAll();
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/IMigrationRunner.cs b/Mongo.Migration/Migrations/IMigrationRunner.cs
index 78f5593..023e3a2 100644
--- a/Mongo.Migration/Migrations/IMigrationRunner.cs
+++ b/Mongo.Migration/Migrations/IMigrationRunner.cs
@@ -1,11 +1,14 @@
using System;
using Mongo.Migration.Documents;
+using Mongo.Migration.Migrations.Locators;
using MongoDB.Bson;
namespace Mongo.Migration.Migrations
{
internal interface IMigrationRunner
{
+ IMigrationLocator _migrationLocator { get; }
+
void Run(Type type, BsonDocument document, DocumentVersion to);
void Run(Type type, BsonDocument document);
diff --git a/Mongo.Migration/Migrations/Locators/AdvancedMigrationLocator.cs b/Mongo.Migration/Migrations/Locators/AdvancedMigrationLocator.cs
new file mode 100644
index 0000000..5e7e77a
--- /dev/null
+++ b/Mongo.Migration/Migrations/Locators/AdvancedMigrationLocator.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Mongo.Migration.Documents;
+using Mongo.Migration.Exceptions;
+using Mongo.Migration.Extensions;
+
+namespace Mongo.Migration.Migrations.Locators
+{
+ public abstract class AdvancedMigrationLocator : IAdvancedMigrationLocator
+ {
+ private IEnumerable _assemblies;
+
+ protected IEnumerable Assemblies => _assemblies ?? (_assemblies = GetAssemblies());
+
+ private IDictionary> _migrations;
+
+ protected IDictionary> Migrations
+ {
+ get
+ {
+ if (_migrations == null)
+ Locate();
+
+ if (_migrations.NullOrEmpty())
+ throw new NoMigrationsFoundException();
+
+ return _migrations;
+ }
+ set { _migrations = value; }
+ }
+
+ public IEnumerable GetMigrations(Type type)
+ {
+ IReadOnlyCollection migrations;
+ Migrations.TryGetValue(type, out migrations);
+
+ return migrations;
+ }
+
+ public IEnumerable GetMigrationsGt(Type type, string version)
+ {
+ var migrations = GetMigrations(type);
+
+ return
+ migrations
+ .Where(m => m.Version.CompareTo(version) > 0)
+ .ToList();
+ }
+
+ public IEnumerable GetMigrationsGtEq(Type type, string version)
+ {
+ var migrations = GetMigrations(type);
+
+ return
+ migrations
+ .Where(m => m.Version.CompareTo(version) >= 0)
+ .ToList();
+ }
+
+ public DocumentVersion GetLatestVersion(Type type)
+ {
+ var migrations = GetMigrations(type);
+
+ return migrations.Max(m => m.Version);
+ }
+
+ public abstract void Locate();
+
+ private static IEnumerable GetAssemblies()
+ {
+ var location = AppDomain.CurrentDomain.BaseDirectory;
+ var path = Path.GetDirectoryName(location);
+
+ if (string.IsNullOrWhiteSpace(path))
+ throw new DirectoryNotFoundException(ErrorTexts.AppDirNotFound);
+
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
+ var migrationAssemblies = Directory.GetFiles(path, "*.MongoMigrations*.dll").Select(Assembly.LoadFile);
+
+ assemblies.AddRange(migrationAssemblies);
+
+ return assemblies;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/Locators/AdvancedTypeMigrationLocator.cs b/Mongo.Migration/Migrations/Locators/AdvancedTypeMigrationLocator.cs
new file mode 100644
index 0000000..57b3081
--- /dev/null
+++ b/Mongo.Migration/Migrations/Locators/AdvancedTypeMigrationLocator.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Linq;
+using Mongo.Migration.Extensions;
+
+namespace Mongo.Migration.Migrations.Locators
+{
+ internal class AdvancedTypeMigrationLocator : AdvancedMigrationLocator
+ {
+ public override void Locate()
+ {
+ var migrationTypes =
+ (from assembly in Assemblies
+ from type in assembly.GetTypes()
+ where typeof(IAdvancedMigration).IsAssignableFrom(type) && !type.IsAbstract
+ select type).Distinct();
+
+ Migrations = migrationTypes.Select(t => (IAdvancedMigration) Activator.CreateInstance(t)).ToMigrationDictionary();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/Locators/IAdvancedMigrationLocator.cs b/Mongo.Migration/Migrations/Locators/IAdvancedMigrationLocator.cs
new file mode 100644
index 0000000..e7ad7cd
--- /dev/null
+++ b/Mongo.Migration/Migrations/Locators/IAdvancedMigrationLocator.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using Mongo.Migration.Documents;
+
+namespace Mongo.Migration.Migrations.Locators
+{
+ public interface IAdvancedMigrationLocator
+ {
+ IEnumerable GetMigrations(Type type);
+
+ IEnumerable GetMigrationsGt(Type type, string version);
+
+ IEnumerable GetMigrationsGtEq(Type type, string version);
+
+ DocumentVersion GetLatestVersion(Type type);
+
+ void Locate();
+ }
+}
\ No newline at end of file
diff --git a/Mongo.Migration/Migrations/MigrationRunner.cs b/Mongo.Migration/Migrations/MigrationRunner.cs
index effd4ca..9431eb2 100644
--- a/Mongo.Migration/Migrations/MigrationRunner.cs
+++ b/Mongo.Migration/Migrations/MigrationRunner.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.Linq;
using Mongo.Migration.Documents;
using Mongo.Migration.Migrations.Locators;
@@ -10,7 +9,7 @@ namespace Mongo.Migration.Migrations
{
internal class MigrationRunner : IMigrationRunner
{
- private readonly IMigrationLocator _migrationLocator;
+ public IMigrationLocator _migrationLocator { get; }
private readonly IVersionService _versionService;
@@ -19,7 +18,7 @@ public MigrationRunner(IMigrationLocator migrationLocator, IVersionService versi
_migrationLocator = migrationLocator;
_versionService = versionService;
}
-
+
public void Run(Type type, BsonDocument document)
{
var documentVersion = _versionService.GetVersionOrDefault(document);
@@ -30,7 +29,7 @@ public void Run(Type type, BsonDocument document)
MigrateUpOrDown(type, document, documentVersion, currentOrLatest);
}
-
+
public void Run(Type type, BsonDocument document, DocumentVersion to)
{
var documentVersion = _versionService.GetVersionOrDefault(document);
diff --git a/Mongo.Migration/Mongo.Migration.csproj b/Mongo.Migration/Mongo.Migration.csproj
index 596c899..4fb9c37 100644
--- a/Mongo.Migration/Mongo.Migration.csproj
+++ b/Mongo.Migration/Mongo.Migration.csproj
@@ -11,8 +11,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Mongo.Migration/MongoMigration.cs b/Mongo.Migration/MongoMigration.cs
index cd32032..df7814b 100644
--- a/Mongo.Migration/MongoMigration.cs
+++ b/Mongo.Migration/MongoMigration.cs
@@ -28,7 +28,6 @@ public void Run()
_runtimeVersionLocator.Locate();
_collectionLocator.Locate();
_startUpVersionLocator.Locate();
-
_migrationService.Migrate();
}
}
diff --git a/Mongo.Migration/Services/MigrationService.cs b/Mongo.Migration/Services/MigrationService.cs
index 292517b..9fcaa6f 100644
--- a/Mongo.Migration/Services/MigrationService.cs
+++ b/Mongo.Migration/Services/MigrationService.cs
@@ -12,14 +12,16 @@ internal class MigrationService : IMigrationService
{
private readonly ILogger _logger;
private readonly ICollectionMigrationRunner _migrationRunner;
+ private readonly IDatabaseMigrationRunner _dbMigrationRunner;
private readonly MigrationInterceptorProvider _provider;
private readonly DocumentVersionSerializer _serializer;
public MigrationService(DocumentVersionSerializer serializer, MigrationInterceptorProvider provider,
- ICollectionMigrationRunner migrationRunner)
+ ICollectionMigrationRunner migrationRunner, IDatabaseMigrationRunner dbMigrationRunner)
: this(serializer, provider, NullLoggerFactory.Instance)
{
_migrationRunner = migrationRunner;
+ _dbMigrationRunner = dbMigrationRunner;
}
private MigrationService(
@@ -43,6 +45,7 @@ public void Migrate()
private void OnStartup()
{
_migrationRunner.RunAll();
+ _dbMigrationRunner.RunAll();
}
private void RegisterSerializer()
diff --git a/Mongo.Migration/Startup/DotNetCore/MongoMigrationExtensions.cs b/Mongo.Migration/Startup/DotNetCore/MongoMigrationExtensions.cs
index 463d774..b3307ee 100644
--- a/Mongo.Migration/Startup/DotNetCore/MongoMigrationExtensions.cs
+++ b/Mongo.Migration/Startup/DotNetCore/MongoMigrationExtensions.cs
@@ -24,9 +24,11 @@ public static void AddMigration(
private static void RegisterDefaults(IServiceCollection services, IMongoMigrationSettings settings)
{
services.AddSingleton(settings);
-
+
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
@@ -36,7 +38,9 @@ private static void RegisterDefaults(IServiceCollection services, IMongoMigratio
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
diff --git a/Mongo.Migration/Startup/DotNetCore/MongoMigrationStartupFilter.cs b/Mongo.Migration/Startup/DotNetCore/MongoMigrationStartupFilter.cs
index 9fbd2af..22414b4 100644
--- a/Mongo.Migration/Startup/DotNetCore/MongoMigrationStartupFilter.cs
+++ b/Mongo.Migration/Startup/DotNetCore/MongoMigrationStartupFilter.cs
@@ -28,7 +28,11 @@ public Action Configure(Action next)
{
try
{
+ _logger.LogInformation("Running migration. Please wait....");
+
_migration.Run();
+
+ _logger.LogInformation("Migration has been done");
}
catch (Exception ex)
{
diff --git a/Mongo.Migration/Startup/MongoMigrationSettings.cs b/Mongo.Migration/Startup/MongoMigrationSettings.cs
index 8a96f03..8a92529 100644
--- a/Mongo.Migration/Startup/MongoMigrationSettings.cs
+++ b/Mongo.Migration/Startup/MongoMigrationSettings.cs
@@ -5,11 +5,13 @@ namespace Mongo.Migration.Startup
public class MongoMigrationSettings : IMongoMigrationSettings
{
public string ConnectionString { get; set; }
-
+
public string Database { get; set; }
public string VersionFieldName { get; set; }
-
+
+ public string RunningVersion { get; set; } = "1.0.0";
+
public MongoClientSettings ClientSettings { get; set; }
}
}
\ No newline at end of file
diff --git a/Mongo.Migration/Startup/Static/ComponentRegistry.cs b/Mongo.Migration/Startup/Static/ComponentRegistry.cs
index e72650f..acbba3b 100644
--- a/Mongo.Migration/Startup/Static/ComponentRegistry.cs
+++ b/Mongo.Migration/Startup/Static/ComponentRegistry.cs
@@ -18,10 +18,10 @@ internal class ComponentRegistry : IComponentRegistry
public ComponentRegistry(IMongoMigrationSettings settings, IContainerAdapter containerAdapter = null)
{
_settings = settings;
-
+
if(containerAdapter == null)
containerAdapter = new LightInjectAdapter(new ServiceContainer());
-
+
_containerAdapter = containerAdapter;
}
@@ -30,7 +30,7 @@ public void RegisterComponents(IMongoClient client)
RegisterDefaults();
_containerAdapter.RegisterInstance(client);
-
+
_containerAdapter.Register();
}
@@ -42,22 +42,23 @@ public TComponent Get() where TComponent : class
private void RegisterDefaults()
{
_containerAdapter.RegisterInstance(_containerAdapter);
-
- _containerAdapter.RegisterSingleton();
-
_containerAdapter.RegisterInstance(_settings);
-
+
+ _containerAdapter.RegisterSingleton();
_containerAdapter.RegisterSingleton();
_containerAdapter.RegisterSingleton();
_containerAdapter.RegisterSingleton();
+ _containerAdapter.Register();
+ _containerAdapter.Register();
_containerAdapter.Register();
_containerAdapter.Register();
_containerAdapter.Register();
-
_containerAdapter.Register();
_containerAdapter.Register();
_containerAdapter.Register();
+ _containerAdapter.Register();
+ _containerAdapter.Register();
_containerAdapter.Register();
}
diff --git a/Mongo.Migration/Utils/MigrationUtils.cs b/Mongo.Migration/Utils/MigrationUtils.cs
new file mode 100644
index 0000000..418cc8a
--- /dev/null
+++ b/Mongo.Migration/Utils/MigrationUtils.cs
@@ -0,0 +1,145 @@
+using System;
+using Microsoft.Extensions.Logging;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Mongo.Migration.Utils
+{
+ public class MigrationUtils
+ {
+ private readonly ILogger logger;
+
+ public MigrationUtils()
+ {
+ this.logger = ApplicationLogging.CreateLogger();
+ }
+
+ public long UpdateInnerDocuments(
+ IMongoDatabase db,
+ BsonDocument documentToUpdate,
+ string collection,
+ string documentField) => this.UpdateInnerDocuments(db, documentToUpdate, collection, documentField, "_id");
+
+ public long UpdateInnerDocuments(
+ IMongoDatabase db,
+ BsonDocument documentToUpdate,
+ string collection,
+ string documentField,
+ string fieldToFilter)
+ {
+ logger.LogInformation($"Updating inner documents: {collection}.{documentField} ({fieldToFilter})...");
+
+ var fieldToFilterValue = documentToUpdate.GetValue(fieldToFilter);
+
+ var filter = Builders.Filter.Eq($"{documentField}.{fieldToFilter}", fieldToFilterValue);
+ var update = Builders.Update.Set(documentField, documentToUpdate);
+ var result = db.GetCollection(collection).UpdateMany(filter, update);
+
+ logger.LogInformation($"Has been modified {result.ModifiedCount} register " +
+ $"da collection {collection}, {documentField}.{fieldToFilter}={fieldToFilterValue}.");
+
+ return result.ModifiedCount;
+ }
+
+ public static BsonValue TryGetValue(BsonDocument document, string attr, ILogger logger)
+ {
+ try
+ {
+ return document[attr];
+ }
+ catch (Exception)
+ {
+ logger.LogWarning($"The attribute {attr} not found in document, returning value null");
+ return BsonNull.Value;
+ }
+ }
+
+ public static void UpdateUniqueIndex(IMongoDatabase db, string collectionName, string field, string indexName, ILogger logger)
+ {
+ try
+ {
+ logger.LogInformation($"Update index {collectionName}.{field}");
+
+ var collection = db.GetCollection(collectionName);
+ collection.Indexes.DropOne(indexName);
+
+ var collation = new Collation("en", strength: new Optional(CollationStrength.Secondary));
+
+ var indexModel = new CreateIndexModel(Builders.IndexKeys.Ascending(field), new CreateIndexOptions
+ {
+ Unique = true,
+ Collation = collation,
+ Name = indexName
+ });
+
+ collection.Indexes.CreateOne(indexModel);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Error creating unique index for field {collectionName}.{field}");
+ }
+ }
+ public static void CreateAscendingIndex(IMongoDatabase db, string collectionName, string field, string indexName, ILogger logger)
+ {
+ try
+ {
+ logger.LogInformation($"Creatinf ascending index: {collectionName}.{field}");
+
+ var collection = db.GetCollection(collectionName);
+
+ var indexModel = new CreateIndexModel(Builders.IndexKeys.Ascending(field), new CreateIndexOptions
+ {
+ Name = indexName
+ });
+
+ collection.Indexes.CreateOne(indexModel);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Error creating ascending index for field {collectionName}.{field}");
+ }
+ }
+
+ public static void CreateDescendingIndex(IMongoDatabase db, string collectionName, string field, string indexName, ILogger logger)
+ {
+ try
+ {
+ logger.LogInformation($"Creating descending index: {collectionName}.{field}");
+
+ var collection = db.GetCollection(collectionName);
+
+ var indexModel = new CreateIndexModel(Builders.IndexKeys.Descending(field), new CreateIndexOptions
+ {
+ Name = indexName
+ });
+
+ collection.Indexes.CreateOne(indexModel);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Error creating descending index for field {collectionName}.{field}");
+ }
+ }
+
+ public static void CreateTextIndex(IMongoDatabase db, string collectionName, string field, string indexName, ILogger logger)
+ {
+ try
+ {
+ logger.LogInformation($"Creating text index: {collectionName}.{field}");
+
+ var collection = db.GetCollection(collectionName);
+
+ var indexModel = new CreateIndexModel(Builders.IndexKeys.Text(field), new CreateIndexOptions
+ {
+ Name = indexName
+ });
+
+ collection.Indexes.CreateOne(indexModel);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Error creating text index for field {collectionName}.{field}");
+ }
+ }
+ }
+}
\ No newline at end of file