Beispiel #1
0
        protected virtual string GetDirectory(
            [NotNull] string projectDir,
            [CanBeNull] string siblingFileName,
            [NotNull] string subnamespace)
        {
            Check.NotEmpty(projectDir, nameof(projectDir));
            Check.NotNull(subnamespace, nameof(subnamespace));

            var defaultDirectory = Path.Combine(projectDir, Path.Combine(subnamespace.Split('.')));

            if (siblingFileName != null)
            {
                var siblingPath = TryGetProjectFile(projectDir, siblingFileName);
                if (siblingPath != null)
                {
                    var lastDirectory = Path.GetDirectoryName(siblingPath);
                    if (!defaultDirectory.Equals(lastDirectory, StringComparison.OrdinalIgnoreCase))
                    {
                        _logger.Value.LogDebug(DesignCoreStrings.ReusingDirectory(siblingFileName));

                        return(lastDirectory);
                    }
                }
            }

            return(defaultDirectory);
        }
Beispiel #2
0
        public virtual MigrationFiles Save(
            [NotNull] string projectDir,
            [NotNull] ScaffoldedMigration migration,
            [CanBeNull] string outputDir)
        {
            Check.NotEmpty(projectDir, nameof(projectDir));
            Check.NotNull(migration, nameof(migration));

            var lastMigrationFileName  = migration.PreviousMigrationId + migration.FileExtension;
            var migrationDirectory     = outputDir ?? GetDirectory(projectDir, lastMigrationFileName, migration.MigrationSubNamespace);
            var migrationFile          = Path.Combine(migrationDirectory, migration.MigrationId + migration.FileExtension);
            var migrationMetadataFile  = Path.Combine(migrationDirectory, migration.MigrationId + ".Designer" + migration.FileExtension);
            var modelSnapshotFileName  = migration.SnapshotName + migration.FileExtension;
            var modelSnapshotDirectory = outputDir ?? GetDirectory(projectDir, modelSnapshotFileName, migration.SnapshotSubnamespace);
            var modelSnapshotFile      = Path.Combine(modelSnapshotDirectory, modelSnapshotFileName);

            _logger.Value.LogDebug(DesignCoreStrings.WritingMigration(migrationFile));
            Directory.CreateDirectory(migrationDirectory);
            File.WriteAllText(migrationFile, migration.MigrationCode, Encoding.UTF8);
            File.WriteAllText(migrationMetadataFile, migration.MetadataCode, Encoding.UTF8);

            _logger.Value.LogDebug(DesignCoreStrings.WritingSnapshot(modelSnapshotFile));
            Directory.CreateDirectory(modelSnapshotDirectory);
            File.WriteAllText(modelSnapshotFile, migration.SnapshotCode, Encoding.UTF8);

            return(new MigrationFiles
            {
                MigrationFile = migrationFile,
                MetadataFile = migrationMetadataFile,
                SnapshotFile = modelSnapshotFile
            });
        }
Beispiel #3
0
        protected virtual void Generate([NotNull] MigrationOperation operation, [NotNull] IndentedStringBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            throw new InvalidOperationException(DesignCoreStrings.UnknownOperation(operation.GetType()));
        }
        public void UnknownLiteral_throws_when_unknown()
        {
            var ex = Assert.Throws <InvalidOperationException>(
                () => new CSharpHelper().UnknownLiteral(new object()));

            Assert.Equal(DesignCoreStrings.UnknownLiteral(typeof(object)), ex.Message);
        }
Beispiel #5
0
        public virtual string UnknownLiteral([CanBeNull] object value)
        {
            if (value == null)
            {
                return("null");
            }

            var type = value.GetType().UnwrapNullableType();

            Func <CSharpHelper, object, string> literalFunc;

            if (_literalFuncs.TryGetValue(type, out literalFunc))
            {
                return(literalFunc(this, value));
            }

            var enumValue = value as Enum;

            if (enumValue != null)
            {
                return(Literal(enumValue));
            }

            throw new InvalidOperationException(DesignCoreStrings.UnknownLiteral(value.GetType()));
        }
Beispiel #6
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual void CheckValidity()
        {
            if (string.IsNullOrEmpty(ConnectionString))
            {
                throw new ArgumentException(DesignCoreStrings.ConnectionStringRequired);
            }

            if (string.IsNullOrEmpty(ProjectPath))
            {
                throw new ArgumentException(DesignCoreStrings.ProjectPathRequired);
            }

            if (!string.IsNullOrWhiteSpace(ContextClassName) &&
                (!CSharpUtilities.Instance.IsValidIdentifier(ContextClassName) ||
                 CSharpUtilities.Instance.IsCSharpKeyword(ContextClassName)))
            {
                throw new ArgumentException(
                          DesignCoreStrings.ContextClassNotValidCSharpIdentifier(ContextClassName));
            }

            if (string.IsNullOrEmpty(ProjectRootNamespace))
            {
                throw new ArgumentException(DesignCoreStrings.RootNamespaceRequired);
            }
        }
        private object Invoke(Type type, string[] methodNames, IServiceCollection services)
        {
            if (type == null)
            {
                return(null);
            }

            MethodInfo method = null;

            // ReSharper disable once ForCanBeConvertedToForeach
            for (var i = 0; i < methodNames.Length; i++)
            {
                method = type.GetTypeInfo().GetDeclaredMethod(methodNames[i]);
                if (method != null)
                {
                    break;
                }
            }

            if (method == null)
            {
                return(null);
            }

            try
            {
                var instance = !method.IsStatic
                    ? ActivatorUtilities.GetServiceOrCreateInstance(GetHostServices(), type)
                    : null;

                var parameters = method.GetParameters();
                var arguments  = new object[parameters.Length];
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameterType = parameters[i].ParameterType;
                    arguments[i] = parameterType == typeof(IServiceCollection)
                        ? services
                        : ActivatorUtilities.GetServiceOrCreateInstance(GetHostServices(), parameterType);
                }

                return(method.Invoke(instance, arguments));
            }
            catch (Exception ex)
            {
                if (ex is TargetInvocationException)
                {
                    ex = ex.InnerException;
                }

                _logger.Value.LogWarning(
                    DesignCoreStrings.InvokeStartupMethodFailed(method.Name, type.DisplayName(), ex.Message));
                _logger.Value.LogDebug(ex.ToString());

                return(null);
            }
        }
Beispiel #8
0
        private Type GetProviderDesignTimeServices(string provider, bool throwOnError)
        {
            Assembly providerAssembly;

            try
            {
                providerAssembly = _assemblyLoader.Load(provider);
            }
            catch (Exception ex)
            {
                if (!throwOnError)
                {
                    return(null);
                }

                throw new OperationException(DesignCoreStrings.CannotFindRuntimeProviderAssembly(provider), ex);
            }

            var providerServicesAttribute = providerAssembly.GetCustomAttribute <DesignTimeProviderServicesAttribute>();

            if (providerServicesAttribute == null)
            {
                if (!throwOnError)
                {
                    return(null);
                }

                throw new InvalidOperationException(
                          DesignCoreStrings.CannotFindDesignTimeProviderAssemblyAttribute(
                              nameof(DesignTimeProviderServicesAttribute),
                              provider));
            }

            Assembly designTimeProviderAssembly;

            try
            {
                designTimeProviderAssembly = _assemblyLoader.Load(providerServicesAttribute.AssemblyName);
            }
            catch (Exception ex)
                when(ex is FileNotFoundException || ex is FileLoadException || ex is BadImageFormatException)
                {
                    if (!throwOnError)
                    {
                        return(null);
                    }

                    throw new OperationException(
                              DesignCoreStrings.CannotFindDesignTimeProviderAssembly(providerServicesAttribute.PackageName), ex);
                }

            return(designTimeProviderAssembly.GetType(
                       providerServicesAttribute.TypeName,
                       throwOnError: true,
                       ignoreCase: false));
        }
Beispiel #9
0
        public void Throws_for_no_parameterless_constructor()
        {
            using (var directory = new TempDirectory())
            {
                var targetDir = directory.Path;
                var source    = new BuildSource
                {
                    TargetDir  = targetDir,
                    References =
                    {
                        BuildReference.ByName("System.Diagnostics.DiagnosticSource",                                             copyLocal: true),
                        BuildReference.ByName("System.Interactive.Async",                                                        copyLocal: true),
                        BuildReference.ByName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"),
                        BuildReference.ByName("Microsoft.AspNetCore.Hosting.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore",                                                   copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools",                                             copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Design.Core",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational",                                        copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational.Design",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer",                                         copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Memory",                                             copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Configuration.Abstractions",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection",                                        copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions",                           copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.FileProviders.Abstractions",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging",                                                    copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Options",                                                    copyLocal: true),
                        BuildReference.ByName("Remotion.Linq",                                                                   copyLocal: true)
                    },
                    Sources = { @"
                            using Microsoft.EntityFrameworkCore;
                            using Microsoft.EntityFrameworkCore.Infrastructure;
                            using Microsoft.EntityFrameworkCore.Migrations;

                            namespace MyProject
                            {
                                internal class MyContext : DbContext
                                {
                                    public MyContext(DbContextOptions<MyContext> options) :base(options)  {}
                                }
                            }" }
                };
                var build = source.Build();
                using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject"))
                {
                    var ex = Assert.Throws <OperationException>(
                        () => executor.GetMigrations("MyContext"));

                    Assert.Equal(
                        DesignCoreStrings.NoParameterlessConstructor("MyContext"),
                        ex.Message);
                }
            }
        }
Beispiel #10
0
        private DbContext CreateContext(Func <DbContext> factory)
        {
            var context = factory();

            _logger.Value.LogDebug(DesignCoreStrings.LogUseContext(context.GetType().ShortDisplayName()));

            var loggerFactory = context.GetService <ILoggerFactory>();

            loggerFactory.AddProvider(_loggerProvider);

            return(context);
        }
Beispiel #11
0
        private KeyValuePair <Type, Func <DbContext> > FindContextType(string name)
        {
            var types = FindContextTypes();

            if (string.IsNullOrEmpty(name))
            {
                if (types.Count == 0)
                {
                    throw new OperationException(DesignCoreStrings.NoContext(_assembly.GetName().Name));
                }
                if (types.Count == 1)
                {
                    return(types.First());
                }

                throw new OperationException(DesignCoreStrings.MultipleContexts);
            }

            var candidates = FilterTypes(types, name, ignoreCase: true);

            if (candidates.Count == 0)
            {
                throw new OperationException(DesignCoreStrings.NoContextWithName(name));
            }
            if (candidates.Count == 1)
            {
                return(candidates.First());
            }

            // Disambiguate using case
            candidates = FilterTypes(candidates, name);
            if (candidates.Count == 0)
            {
                throw new OperationException(DesignCoreStrings.MultipleContextsWithName(name));
            }
            if (candidates.Count == 1)
            {
                return(candidates.First());
            }

            // Allow selecting types in the default namespace
            candidates = candidates.Where(t => t.Key.Namespace == null).ToDictionary(t => t.Key, t => t.Value);
            if (candidates.Count == 0)
            {
                throw new OperationException(DesignCoreStrings.MultipleContextsWithQualifiedName(name));
            }

            Debug.Assert(candidates.Count == 1, "candidates.Count is not 1.");

            return(candidates.First());
        }
        public void Throws_exceptions_for_incorrect_configuration()
        {
            var configuration = new ReverseEngineeringConfiguration
            {
                ConnectionString = null,
                ProjectPath      = null,
                OutputPath       = null
            };

            Assert.Equal(DesignCoreStrings.ConnectionStringRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ConnectionString = "NonEmptyConnectionString";
            Assert.Equal(DesignCoreStrings.ProjectPathRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ProjectPath = "NonEmptyProjectPath";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = @"Invalid!CSharp*Class&Name";
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier(@"Invalid!CSharp*Class&Name"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "1CSharpClassNameCannotStartWithNumber";
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier("1CSharpClassNameCannotStartWithNumber"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "volatile"; // cannot be C# keyword
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier("volatile"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "GoodClassName";
            configuration.OutputPath       = @"\AnAbsolutePath";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.OutputPath = @"A\Relative\Path";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);
        }
Beispiel #13
0
        protected virtual string GetNamespace([CanBeNull] Type siblingType, [NotNull] string defaultNamespace)
        {
            if (siblingType != null)
            {
                var lastNamespace = siblingType.Namespace;
                if (lastNamespace != defaultNamespace)
                {
                    _logger.Value.LogDebug(DesignCoreStrings.ReusingNamespace(siblingType.ShortDisplayName()));

                    return(lastNamespace);
                }
            }

            return(defaultNamespace);
        }
        private static void SerializeObject(object obj, IndentedStringBuilder sb)
        {
            if (obj == null)
            {
                sb.Append("null");
                return;
            }
            if (obj is string)
            {
                SerializeString(obj as string, sb);
                return;
            }
            if (obj is bool)
            {
                sb.Append(((bool)obj)
                    ? "true"
                    : "false");
                return;
            }
            if (obj is short ||
                obj is ushort ||
                obj is int ||
                obj is uint ||
                obj is long ||
                obj is ulong ||
                obj is decimal ||
                obj is float ||
                obj is double)
            {
                sb.Append(obj);
                return;
            }
            if (obj is IEnumerable)
            {
                SerializeEnumerable(obj as IEnumerable, sb);
                return;
            }
            if (obj.GetType().GetTypeInfo().IsClass)
            {
                SerializeClass(obj, sb);
                return;
            }

            throw new ArgumentException(DesignCoreStrings.CouldNotSerialize(obj, obj.GetType().FullName));
        }
Beispiel #15
0
        public void Invoke_warns_on_error()
        {
            var log = new List <Tuple <LogLevel, string> >();

            var startup = new StartupInvoker(
                new LazyRef <ILogger>(() => new ListLoggerFactory(log).CreateLogger("Test")),
                MockAssembly.Create(typeof(BadStartup)),
                /*environment:*/ null,
                "Irrelevant");

            var services = startup.ConfigureServices();

            Assert.NotNull(services);
            Assert.Equal(
                DesignCoreStrings.InvokeStartupMethodFailed(
                    "ConfigureServices",
                    nameof(BadStartup),
                    "Something went wrong."),
                log[0].Item2);
        }
        private void EnsureServices(IServiceProvider services)
        {
            var providerServices = services.GetRequiredService <IDatabaseProviderServices>();

            if (!(providerServices is IRelationalDatabaseProviderServices))
            {
                throw new OperationException(DesignCoreStrings.NonRelationalProvider(providerServices.InvariantName));
            }

            var assemblyName           = _assembly.GetName();
            var options                = services.GetRequiredService <IDbContextOptions>();
            var contextType            = services.GetRequiredService <ICurrentDbContext>().Context.GetType();
            var migrationsAssemblyName = RelationalOptionsExtension.Extract(options).MigrationsAssembly
                                         ?? contextType.GetTypeInfo().Assembly.GetName().Name;

            if (assemblyName.Name != migrationsAssemblyName &&
                assemblyName.FullName != migrationsAssemblyName)
            {
                throw new OperationException(
                          DesignCoreStrings.MigrationsAssemblyMismatch(assemblyName.Name, migrationsAssemblyName));
            }
        }
        protected override void Generate([NotNull] MigrationOperation operation, [NotNull] IndentedStringBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            var asCreateExtensionOperation = operation as NpgsqlCreatePostgresExtensionOperation;

            if (asCreateExtensionOperation != null)
            {
                Generate(asCreateExtensionOperation, builder);
                return;
            }

            var asDropExtensionOperation = operation as NpgsqlDropPostgresExtensionOperation;

            if (asDropExtensionOperation != null)
            {
                Generate(asDropExtensionOperation, builder);
                return;
            }

            throw new InvalidOperationException(DesignCoreStrings.UnknownOperation(operation.GetType()));
        }
Beispiel #18
0
 public virtual void DropDatabase([CanBeNull] string contextType, [NotNull] Func <string, string, bool> confirmCheck)
 {
     using (var context = CreateContext(contextType))
     {
         var connection = context.Database.GetDbConnection();
         if (confirmCheck(connection.Database, connection.DataSource))
         {
             _logger.Value.LogInformation(DesignCoreStrings.LogDroppingDatabase(connection.Database));
             if (context.Database.EnsureDeleted())
             {
                 _logger.Value.LogInformation(DesignCoreStrings.LogDatabaseDropped(connection.Database));
             }
             else
             {
                 _logger.Value.LogInformation(DesignCoreStrings.LogNotExistDatabase(connection.Database));
             }
         }
         else
         {
             _logger.Value.LogInformation(DesignCoreStrings.Cancelled);
         }
     }
 }
Beispiel #19
0
        public virtual ScaffoldedMigration ScaffoldMigration(
            [NotNull] string migrationName,
            [NotNull] string rootNamespace,
            [CanBeNull] string subNamespace = null)
        {
            Check.NotEmpty(migrationName, nameof(migrationName));
            Check.NotEmpty(rootNamespace, nameof(rootNamespace));

            if (_migrationsAssembly.FindMigrationId(migrationName) != null)
            {
                throw new InvalidOperationException(DesignCoreStrings.DuplicateMigrationName(migrationName));
            }

            var subNamespaceDefaulted = false;

            if (string.IsNullOrEmpty(subNamespace))
            {
                subNamespaceDefaulted = true;
                subNamespace          = "Migrations";
            }

            var lastMigration = _migrationsAssembly.Migrations.LastOrDefault();

            var migrationNamespace = rootNamespace + "." + subNamespace;

            if (subNamespaceDefaulted)
            {
                migrationNamespace = GetNamespace(lastMigration.Value?.AsType(), migrationNamespace);
            }

            var sanitizedContextName = _contextType.Name;
            var genericMarkIndex     = sanitizedContextName.IndexOf('`');

            if (genericMarkIndex != -1)
            {
                sanitizedContextName = sanitizedContextName.Substring(0, genericMarkIndex);
            }

            if (ContainsForeignMigrations(migrationNamespace))
            {
                if (subNamespaceDefaulted)
                {
                    var builder = new StringBuilder()
                                  .Append(rootNamespace)
                                  .Append(".Migrations.");

                    if (sanitizedContextName.EndsWith("Context", StringComparison.Ordinal))
                    {
                        builder.Append(sanitizedContextName.Substring(0, sanitizedContextName.Length - 7));
                    }
                    else
                    {
                        builder
                        .Append(sanitizedContextName)
                        .Append("Migrations");
                    }

                    migrationNamespace = builder.ToString();
                }
                else
                {
                    _logger.Value.LogWarning(DesignCoreStrings.ForeignMigrations(migrationNamespace));
                }
            }

            var modelSnapshot  = _migrationsAssembly.ModelSnapshot;
            var lastModel      = modelSnapshot?.Model;
            var upOperations   = _modelDiffer.GetDifferences(lastModel, _model);
            var downOperations = upOperations.Any()
                ? _modelDiffer.GetDifferences(_model, lastModel)
                : new List <MigrationOperation>();
            var migrationId            = _idGenerator.GenerateId(migrationName);
            var modelSnapshotNamespace = GetNamespace(modelSnapshot?.GetType(), migrationNamespace);

            var modelSnapshotName = sanitizedContextName + "ModelSnapshot";

            if (modelSnapshot != null)
            {
                var lastModelSnapshotName = modelSnapshot.GetType().Name;
                if (lastModelSnapshotName != modelSnapshotName)
                {
                    _logger.Value.LogDebug(DesignCoreStrings.ReusingSnapshotName(lastModelSnapshotName));

                    modelSnapshotName = lastModelSnapshotName;
                }
            }

            if (upOperations.Any(o => o.IsDestructiveChange))
            {
                _logger.Value.LogWarning(DesignCoreStrings.DestructiveOperation);
            }

            var migrationCode = _migrationCodeGenerator.GenerateMigration(
                migrationNamespace,
                migrationName,
                upOperations,
                downOperations);
            var migrationMetadataCode = _migrationCodeGenerator.GenerateMetadata(
                migrationNamespace,
                _contextType,
                migrationName,
                migrationId,
                _model);
            var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot(
                modelSnapshotNamespace,
                _contextType,
                modelSnapshotName,
                _model);

            return(new ScaffoldedMigration(
                       _migrationCodeGenerator.FileExtension,
                       lastMigration.Key,
                       migrationCode,
                       migrationId,
                       migrationMetadataCode,
                       GetSubNamespace(rootNamespace, migrationNamespace),
                       modelSnapshotCode,
                       modelSnapshotName,
                       GetSubNamespace(rootNamespace, modelSnapshotNamespace)));
        }
Beispiel #20
0
        public void GetMigrations_throws_when_target_and_migrations_assemblies_mismatch()
        {
            using (var directory = new TempDirectory())
            {
                var targetDir = directory.Path;
                var source    = new BuildSource
                {
                    TargetDir  = targetDir,
                    References =
                    {
                        BuildReference.ByName("System.Diagnostics.DiagnosticSource",                                             copyLocal: true),
                        BuildReference.ByName("System.Interactive.Async",                                                        copyLocal: true),
                        BuildReference.ByName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"),
                        BuildReference.ByName("Microsoft.AspNetCore.Hosting.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore",                                                   copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools",                                             copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Design.Core",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational",                                        copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational.Design",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer",                                         copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Memory",                                             copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Configuration.Abstractions",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection",                                        copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions",                           copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.FileProviders.Abstractions",                                 copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging",                                                    copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Options",                                                    copyLocal: true),
                        BuildReference.ByName("Remotion.Linq",                                                                   copyLocal: true)
                    },
                    Sources = { @"
                            using Microsoft.EntityFrameworkCore;
                            using Microsoft.EntityFrameworkCore.Infrastructure;
                            using Microsoft.EntityFrameworkCore.Migrations;

                            namespace MyProject
                            {
                                internal class MyContext : DbContext
                                {
                                    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
                                    {
                                        optionsBuilder
                                            .UseSqlServer(
                                                ""Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MyProject.MyContext;Integrated Security=True"",
                                                b => b.MigrationsAssembly(""UnknownAssembly""));
                                    }
                                }

                                namespace Migrations
                                {
                                    [DbContext(typeof(MyContext))]
                                    [Migration(""20151215152142_MyMigration"")]
                                    public class MyMigration : Migration
                                    {
                                        protected override void Up(MigrationBuilder migrationBuilder)
                                        {
                                        }
                                    }
                                }
                            }" }
                };
                var build = source.Build();
                using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject"))
                {
                    var ex = Assert.Throws <OperationException>(
                        () => executor.GetMigrations("MyContext"));

                    Assert.Equal(
                        DesignCoreStrings.MigrationsAssemblyMismatch(build.TargetName, "UnknownAssembly"),
                        ex.Message);
                }
            }
        }
        public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args, [NotNull] AssemblyLoader assemblyLoader)
        {
            Check.NotNull(logHandler, nameof(logHandler));
            Check.NotNull(args, nameof(args));
            Check.NotNull(assemblyLoader, nameof(assemblyLoader));

            var unwrappedLogHandler = ForwardingProxy.Unwrap <IOperationLogHandler>(logHandler);
            var loggerProvider      = new LoggerProvider(name => new CommandLoggerAdapter(name, unwrappedLogHandler));

            var targetName        = (string)args["targetName"];
            var startupTargetName = (string)args["startupTargetName"];
            var environment       = (string)args["environment"];

            _projectDir = (string)args["projectDir"];
            var contentRootPath = (string)args["contentRootPath"];
            var rootNamespace   = (string)args["rootNamespace"];

            // NOTE: LazyRef is used so any exceptions get passed to the resultHandler
            var startupAssembly = new LazyRef <Assembly>(
                () => assemblyLoader.Load(startupTargetName));
            var assembly = new LazyRef <Assembly>(
                () =>
            {
                try
                {
                    return(assemblyLoader.Load(targetName));
                }
                catch (Exception ex)
                {
                    throw new OperationException(
                        DesignCoreStrings.UnreferencedAssembly(targetName, startupTargetName),
                        ex);
                }
            });

            _contextOperations = new LazyRef <DbContextOperations>(
                () => new DbContextOperations(
                    loggerProvider,
                    assembly.Value,
                    startupAssembly.Value,
                    environment,
                    contentRootPath));
            _databaseOperations = new LazyRef <DatabaseOperations>(
                () => new DatabaseOperations(
                    loggerProvider,
                    assemblyLoader,
                    startupAssembly.Value,
                    environment,
                    _projectDir,
                    contentRootPath,
                    rootNamespace));
            _migrationsOperations = new LazyRef <MigrationsOperations>(
                () => new MigrationsOperations(
                    loggerProvider,
                    assembly.Value,
                    assemblyLoader,
                    startupAssembly.Value,
                    environment,
                    _projectDir,
                    contentRootPath,
                    rootNamespace));
        }
Beispiel #22
0
        // TODO: DRY (file names)
        public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotNull] string rootNamespace, bool force)
        {
            Check.NotEmpty(projectDir, nameof(projectDir));
            Check.NotEmpty(rootNamespace, nameof(rootNamespace));

            var files = new MigrationFiles();

            var modelSnapshot = _migrationsAssembly.ModelSnapshot;

            if (modelSnapshot == null)
            {
                throw new InvalidOperationException(DesignCoreStrings.NoSnapshot);
            }

            var language = _migrationCodeGenerator.FileExtension;

            IModel model      = null;
            var    migrations = _migrationsAssembly.Migrations
                                .Select(m => _migrationsAssembly.CreateMigration(m.Value, _activeProvider))
                                .ToList();

            if (migrations.Count != 0)
            {
                var migration = migrations[migrations.Count - 1];
                model = migration.TargetModel;

                if (!_modelDiffer.HasDifferences(model, modelSnapshot.Model))
                {
                    if (force)
                    {
                        _logger.Value.LogWarning(DesignCoreStrings.ForceRemoveMigration(migration.GetId()));
                    }
                    else if (_historyRepository.GetAppliedMigrations().Any(
                                 e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase)))
                    {
                        throw new InvalidOperationException(DesignCoreStrings.UnapplyMigration(migration.GetId()));
                    }

                    var migrationFileName = migration.GetId() + language;
                    var migrationFile     = TryGetProjectFile(projectDir, migrationFileName);
                    if (migrationFile != null)
                    {
                        _logger.Value.LogInformation(DesignCoreStrings.RemovingMigration(migration.GetId()));
                        File.Delete(migrationFile);
                        files.MigrationFile = migrationFile;
                    }
                    else
                    {
                        _logger.Value.LogWarning(
                            DesignCoreStrings.NoMigrationFile(migrationFileName, migration.GetType().ShortDisplayName()));
                    }

                    var migrationMetadataFileName = migration.GetId() + ".Designer" + language;
                    var migrationMetadataFile     = TryGetProjectFile(projectDir, migrationMetadataFileName);
                    if (migrationMetadataFile != null)
                    {
                        File.Delete(migrationMetadataFile);
                        files.MetadataFile = migrationMetadataFile;
                    }
                    else
                    {
                        _logger.Value.LogDebug(DesignCoreStrings.NoMigrationMetadataFile(migrationMetadataFileName));
                    }

                    model = migrations.Count > 1
                        ? migrations[migrations.Count - 2].TargetModel
                        : null;
                }
                else
                {
                    _logger.Value.LogDebug(DesignCoreStrings.ManuallyDeleted);
                }
            }

            var modelSnapshotName     = modelSnapshot.GetType().Name;
            var modelSnapshotFileName = modelSnapshotName + language;
            var modelSnapshotFile     = TryGetProjectFile(projectDir, modelSnapshotFileName);

            if (model == null)
            {
                if (modelSnapshotFile != null)
                {
                    _logger.Value.LogInformation(DesignCoreStrings.RemovingSnapshot);
                    File.Delete(modelSnapshotFile);
                    files.SnapshotFile = modelSnapshotFile;
                }
                else
                {
                    _logger.Value.LogWarning(
                        DesignCoreStrings.NoSnapshotFile(modelSnapshotFileName, modelSnapshot.GetType().ShortDisplayName()));
                }
            }
            else
            {
                var modelSnapshotNamespace = modelSnapshot.GetType().Namespace;
                Debug.Assert(!string.IsNullOrEmpty(modelSnapshotNamespace));
                var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot(
                    modelSnapshotNamespace,
                    _contextType,
                    modelSnapshotName,
                    model);

                if (modelSnapshotFile == null)
                {
                    modelSnapshotFile = Path.Combine(
                        GetDirectory(projectDir, null, GetSubNamespace(rootNamespace, modelSnapshotNamespace)),
                        modelSnapshotFileName);
                }

                _logger.Value.LogInformation(DesignCoreStrings.RevertingSnapshot);
                File.WriteAllText(modelSnapshotFile, modelSnapshotCode, Encoding.UTF8);
            }

            return(files);
        }
Beispiel #23
0
        private IDictionary <Type, Func <DbContext> > FindContextTypes()
        {
            _logger.Value.LogDebug(DesignCoreStrings.LogFindingContexts);

            var contexts = new Dictionary <Type, Func <DbContext> >();

            // Look for IDbContextFactory implementations
            var contextFactories = _startupAssembly.GetConstructableTypes()
                                   .Where(t => typeof(IDbContextFactory <DbContext>).GetTypeInfo().IsAssignableFrom(t));

            foreach (var factory in contextFactories)
            {
                var manufacturedContexts =
                    from i in factory.ImplementedInterfaces
                    where i.GetTypeInfo().IsGenericType &&
                    i.GetGenericTypeDefinition() == typeof(IDbContextFactory <>)
                    select i.GenericTypeArguments[0];
                foreach (var context in manufacturedContexts)
                {
                    contexts.Add(
                        context,
                        () => ((IDbContextFactory <DbContext>)Activator.CreateInstance(factory.AsType())).Create(
                            CreateFactoryOptions()));
                }
            }

            // Look for DbContext classes registered in the service provider
            var registeredContexts = _runtimeServices.GetServices <DbContextOptions>()
                                     .Select(o => o.ContextType);

            foreach (var context in registeredContexts.Where(c => !contexts.ContainsKey(c)))
            {
                contexts.Add(
                    context,
                    FindContextFactory(context) ?? (() => (DbContext)_runtimeServices.GetRequiredService(context)));
            }

            // Look for DbContext classes in assemblies
            var types = _startupAssembly.GetConstructableTypes()
                        .Concat(_assembly.GetConstructableTypes())
                        .Select(i => i.AsType())
                        .ToList();
            var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t))
                               .Concat(
                types.Where(t => typeof(Migration).IsAssignableFrom(t))
                .Select(t => t.GetTypeInfo().GetCustomAttribute <DbContextAttribute>()?.ContextType)
                .Where(t => t != null))
                               .Distinct();

            foreach (var context in contextTypes.Where(c => !contexts.ContainsKey(c)))
            {
                contexts.Add(
                    context,
                    FindContextFactory(context) ?? (Func <DbContext>)(() =>
                {
                    try
                    {
                        return((DbContext)Activator.CreateInstance(context));
                    }
                    catch (MissingMethodException ex)
                    {
                        throw new OperationException(DesignCoreStrings.NoParameterlessConstructor(context.Name), ex);
                    }
                }));
            }

            return(contexts);
        }