Ejemplo n.º 1
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(CommandsStrings.UnknownLiteral(value.GetType()));
        }
        public OperationsFactory([CanBeNull] string startupProject, [CanBeNull] string environment)
        {
            var project = Directory.GetCurrentDirectory();

            startupProject = startupProject ?? project;

            var startupProjectContext = ProjectContext.CreateContextForEachFramework(startupProject).First();
            var projectContext        = ProjectContext.CreateContextForEachFramework(project).First();
            var startupAssemblyName   = new AssemblyName(startupProjectContext.ProjectFile.Name);
            var assemblyName          = new AssemblyName(projectContext.ProjectFile.Name);
            var assemblyLoadContext   = startupProjectContext.CreateLoadContext();

            _startupAssembly = assemblyLoadContext.LoadFromAssemblyName(startupAssemblyName);

            try
            {
                _assembly = assemblyLoadContext.LoadFromAssemblyName(assemblyName);
            }
            catch (Exception ex)
            {
                throw new OperationException(
                          CommandsStrings.UnreferencedAssembly(
                              projectContext.ProjectFile.Name,
                              startupProjectContext.ProjectFile.Name),
                          ex);
            }
            _environment   = environment;
            _projectDir    = projectContext.ProjectDirectory;
            _rootNamespace = projectContext.ProjectFile.Name;
        }
        private IEnumerable <MethodInfo> MakeGenericMethods(MethodInfo declaringMethod)
        {
            var usages = declaringMethod.GetCustomAttributes <CallsMakeGenericMethodAttribute>();

            foreach (var usage in usages)
            {
                var methodDefinition = usage.FindMethodInfo(declaringMethod);

                if (methodDefinition == null)
                {
                    throw new InvalidOperationException(CommandsStrings.InvalidCallsMakeGenericMethodAttribute(declaringMethod.DeclaringType.FullName + "." + declaringMethod.Name));
                }

                foreach (var typeArgs in BindTypeArguments(new ArraySegment <Type>(usage.TypeArguments)).Distinct())
                {
                    MethodInfo boundMethod;
                    try
                    {
                        boundMethod = methodDefinition.MakeGenericMethod(typeArgs);
                    }
                    catch (ArgumentException)
                    {
                        // ignores type constraints violations
                        continue;
                    }
                    yield return(boundMethod);
                }
            }
        }
Ejemplo n.º 4
0
        protected virtual void Generate([NotNull] MigrationOperation operation, [NotNull] IndentedStringBuilder builder)
        {
            Check.NotNull(operation, nameof(operation));
            Check.NotNull(builder, nameof(builder));

            throw new InvalidOperationException(CommandsStrings.UnknownOperation(operation.GetType()));
        }
Ejemplo n.º 5
0
        public void UnknownLiteral_throws_when_unknown()
        {
            var ex = Assert.Throws <InvalidOperationException>(
                () => new CSharpHelper().UnknownLiteral(new object()));

            Assert.Equal(CommandsStrings.UnknownLiteral(typeof(object)), ex.Message);
        }
        public virtual MigrationFiles Save([NotNull] string projectDir, [NotNull] ScaffoldedMigration migration)
        {
            Check.NotEmpty(projectDir, nameof(projectDir));
            Check.NotNull(migration, nameof(migration));

            var lastMigrationFileName  = migration.PreviousMigrationId + migration.FileExtension;
            var migrationDirectory     = 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 = GetDirectory(projectDir, modelSnapshotFileName, migration.SnapshotSubnamespace);
            var modelSnapshotFile      = Path.Combine(modelSnapshotDirectory, modelSnapshotFileName);

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

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

            return(new MigrationFiles
            {
                MigrationFile = migrationFile,
                MetadataFile = migrationMetadataFile,
                SnapshotFile = modelSnapshotFile
            });
        }
        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(CommandsStrings.ReusingDirectory(siblingFileName));

                        return(lastDirectory);
                    }
                }
            }

            return(defaultDirectory);
        }
Ejemplo n.º 8
0
        public virtual void CheckValidity()
        {
            if (string.IsNullOrEmpty(ConnectionString))
            {
                throw new ArgumentException(CommandsStrings.ConnectionStringRequired);
            }

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

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

            if (string.IsNullOrEmpty(ProjectRootNamespace))
            {
                throw new ArgumentException(CommandsStrings.RootNamespaceRequired);
            }
        }
Ejemplo n.º 9
0
        public virtual Type GetContextType([CanBeNull] string name)
        {
            var contextType = FindContextType(name);

            _logger.Value.LogVerbose(CommandsStrings.LogUseContext(contextType.Name));

            return(contextType);
        }
Ejemplo n.º 10
0
        private static void EnsureServices(IServiceProvider services)
        {
            var providerServices = services.GetRequiredService <IDatabaseProviderServices>();

            if (!(providerServices is IRelationalDatabaseProviderServices))
            {
                throw new OperationException(CommandsStrings.NonRelationalProvider(providerServices.InvariantName));
            }
        }
        private DbContext CreateContext(Func <DbContext> factory)
        {
            var context = factory();

            _logger.Value.LogDebug(CommandsStrings.LogUseContext(context.GetType().Name));

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

            loggerFactory.AddProvider(_loggerProvider);

            return(context);
        }
Ejemplo n.º 12
0
        private Type FindContextType(string name)
        {
            var types = GetContextTypes();

            Type[] candidates;

            if (string.IsNullOrEmpty(name))
            {
                candidates = types.Take(2).ToArray();
                if (candidates.Length == 0)
                {
                    throw new OperationException(CommandsStrings.NoContext);
                }
                if (candidates.Length == 1)
                {
                    return(candidates[0]);
                }

                throw new OperationException(CommandsStrings.MultipleContexts);
            }

            candidates = FilterTypes(types, name, ignoreCase: true).ToArray();
            if (candidates.Length == 0)
            {
                throw new OperationException(CommandsStrings.NoContextWithName(name));
            }
            if (candidates.Length == 1)
            {
                return(candidates[0]);
            }

            // Disambiguate using case
            candidates = FilterTypes(candidates, name).ToArray();
            if (candidates.Length == 0)
            {
                throw new OperationException(CommandsStrings.MultipleContextsWithName(name));
            }
            if (candidates.Length == 1)
            {
                return(candidates[0]);
            }

            // Allow selecting types in the default namespace
            candidates = candidates.Where(t => t.Namespace == null).ToArray();
            if (candidates.Length == 0)
            {
                throw new OperationException(CommandsStrings.MultipleContextsWithQualifiedName(name));
            }

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

            return(candidates[0]);
        }
Ejemplo n.º 13
0
        public virtual DbContext CreateContext([CanBeNull] string contextType)
        {
            var context = FindContextType(contextType).Value();

            _logger.Value.LogDebug(CommandsStrings.LogUseContext(context.GetType().Name));

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

            loggerFactory.AddProvider(_loggerProvider);

            return(context);
        }
Ejemplo n.º 14
0
        private static Type GetProviderDesignTimeServices(string provider, bool throwOnError)
        {
            Assembly providerAssembly;

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

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

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

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

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

            try
            {
                return(Type.GetType(
                           providerServicesAttribute.FullyQualifiedTypeName,
                           throwOnError: true,
                           ignoreCase: false));
            }
            catch (Exception ex)
                when(ex is FileNotFoundException || ex is FileLoadException || ex is BadImageFormatException)
                {
                    if (!throwOnError)
                    {
                        return(null);
                    }

                    throw new OperationException(
                              CommandsStrings.CannotFindDesignTimeProviderAssembly(providerServicesAttribute.PackageName), ex);
                }
        }
Ejemplo n.º 15
0
        private KeyValuePair <Type, Func <DbContext> > FindContextType(string name)
        {
            var types = FindContextTypes();

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

                throw new OperationException(CommandsStrings.MultipleContexts);
            }

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

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

            // Disambiguate using case
            candidates = FilterTypes(candidates, name);
            if (candidates.Count == 0)
            {
                throw new OperationException(CommandsStrings.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(CommandsStrings.MultipleContextsWithQualifiedName(name));
            }

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

            return(candidates.First());
        }
Ejemplo n.º 16
0
        public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args)
        {
            Check.NotNull(logHandler, nameof(logHandler));
            Check.NotNull(args, nameof(args));

            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"];
            var projectDir        = (string)args["projectDir"];
            var rootNamespace     = (string)args["rootNamespace"];

            var startupAssembly = Assembly.Load(new AssemblyName(startupTargetName));

            Assembly assembly;

            try
            {
                assembly = Assembly.Load(new AssemblyName(targetName));
            }
            catch (Exception ex)
            {
                throw new OperationException(CommandsStrings.UnreferencedAssembly(targetName, startupTargetName), ex);
            }

            _contextOperations = new LazyRef <DbContextOperations>(
                () => new DbContextOperations(
                    loggerProvider,
                    assembly,
                    startupAssembly,
                    projectDir, environment));
            _databaseOperations = new LazyRef <DatabaseOperations>(
                () => new DatabaseOperations(
                    loggerProvider,
                    assembly,
                    startupAssembly,
                    environment,
                    projectDir,
                    rootNamespace));
            _migrationsOperations = new LazyRef <MigrationsOperations>(
                () => new MigrationsOperations(
                    loggerProvider,
                    assembly,
                    startupAssembly,
                    environment,
                    projectDir,
                    rootNamespace));
        }
        private static IDesignTimeMetadataProviderFactory GetProviderDesignTimeServicesBuilder(string provider)
        {
            Assembly providerAssembly;

            try
            {
                providerAssembly = Assembly.Load(new AssemblyName(provider));
            }
            catch (Exception ex)
            {
                throw new OperationException(CommandsStrings.CannotFindRuntimeProviderAssembly(provider), ex);
            }

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

            if (providerServicesAttribute == null)
            {
                throw new InvalidOperationException(
                          CommandsStrings.CannotFindDesignTimeProviderAssemblyAttribute(
                              nameof(DesignTimeProviderServicesAttribute),
                              provider));
            }

            var      providerServicesAssemblyName = providerServicesAttribute.AssemblyName;
            Assembly providerServicesAssembly;

            if (providerServicesAssemblyName != null)
            {
                try
                {
                    providerServicesAssembly = Assembly.Load(new AssemblyName(providerServicesAssemblyName));
                }
                catch (Exception ex)
                {
                    throw new OperationException(
                              CommandsStrings.CannotFindDesignTimeProviderAssembly(providerServicesAssemblyName), ex);
                }
            }
            else
            {
                providerServicesAssembly = providerAssembly;
            }

            var providerServicesType = providerServicesAssembly.GetType(
                providerServicesAttribute.TypeName,
                throwOnError: true,
                ignoreCase: false);

            return((IDesignTimeMetadataProviderFactory)Activator.CreateInstance(providerServicesType));
        }
        public void Throws_exceptions_for_incorrect_configuration()
        {
            var configuration = new ReverseEngineeringConfiguration
            {
                ConnectionString = null,
                ProjectPath      = null,
                OutputPath       = null
            };

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

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

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

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

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

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

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

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

                    return(lastNamespace);
                }
            }

            return(defaultNamespace);
        }
Ejemplo n.º 20
0
        private Assembly GetAssembly()
        {
            if (_assembly == null)
            {
                try
                {
                    _assembly = Assembly.Load(new AssemblyName(_assemblyName));
                }
                catch (Exception ex)
                {
                    throw new OperationException(CommandsStrings.UnreferencedAssembly(_assemblyName, _startupAssemblyName), ex);
                }
            }

            return(_assembly);
        }
        public virtual DirectiveFiles GenerateRuntimeDirectives()
        {
            var generator = new DirectiveGenerator();
            var members   = new List <MemberInfo>();

            foreach (var contextType in FindContextTypes())
            {
                var contextTypeName = contextType.Key.GetTypeInfo().FullName;
                using (var context = CreateContext(contextType.Value))
                {
                    var services   = _servicesBuilder.Build(context);
                    var discoverer = services.GetRequiredService <RuntimeTypeDiscoverer>();

                    _logger.Value.LogDebug(CommandsStrings.BeginRuntimeTypeDiscovery(contextTypeName));
                    var start = members.Count;

                    var assemblies = new[]
                    {
                        typeof(EntityType).GetTypeInfo().Assembly,
                        typeof(RelationalDatabase).GetTypeInfo().Assembly,
                        context.GetInfrastructure()
                        .GetRequiredService <IDbContextServices>()
                        .DatabaseProviderServices
                        .GetType()
                        .GetTypeInfo()
                        .Assembly
                    };

                    members.AddRange(discoverer.Discover(assemblies));

                    _logger.Value.LogDebug(CommandsStrings.EndRuntimeTypeDiscovery(members.Count - start, contextTypeName));
                }
            }
            var xml = generator.GenerateXml(members);

            var filename = Path.Combine(_projectDir, "Properties", "Microsoft.EntityFrameworkCore.g.rd.xml");

            Directory.CreateDirectory(Path.GetDirectoryName(filename));

            _logger.Value.LogInformation(CommandsStrings.WritingDirectives(filename));

            File.WriteAllText(filename, xml);

            return(new DirectiveFiles {
                GeneratedFile = filename
            });
        }
Ejemplo n.º 22
0
        private void EnsureServices(IServiceProvider services)
        {
            var providerServices = services.GetRequiredService <IDatabaseProviderServices>();

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

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

            if (_assemblyName != assemblyName)
            {
                throw new OperationException(CommandsStrings.MigrationsAssemblyMismatch(_assemblyName, assemblyName));
            }
        }
Ejemplo n.º 23
0
        public virtual ScaffoldedMigration ScaffoldMigration(
            [NotNull] string migrationName,
            [NotNull] string rootNamespace)
        {
            Check.NotEmpty(migrationName, nameof(migrationName));
            Check.NotEmpty(rootNamespace, nameof(rootNamespace));

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

            var lastMigration      = _migrationsAssembly.Migrations.LastOrDefault();
            var migrationNamespace = GetNamespace(lastMigration.Value?.AsType(), rootNamespace + ".Migrations");
            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 = _contextType.Name + "ModelSnapshot";

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

                    modelSnapshotName = lastModelSnapshotName;
                }
            }

            if (upOperations.Any(o => o.IsDestructiveChange))
            {
                _logger.Value.LogWarning(CommandsStrings.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)));
        }
        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(CommandsStrings.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"))
                    {
                        builder.Append(sanitizedContextName.Substring(0, sanitizedContextName.Length - 7));
                    }
                    else
                    {
                        builder
                        .Append(sanitizedContextName)
                        .Append("Migrations");
                    }

                    migrationNamespace = builder.ToString();
                }
                else
                {
                    _logger.Value.LogWarning(CommandsStrings.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(CommandsStrings.ReusingSnapshotName(lastModelSnapshotName));

                    modelSnapshotName = lastModelSnapshotName;
                }
            }

            if (upOperations.Any(o => o.IsDestructiveChange))
            {
                _logger.Value.LogWarning(CommandsStrings.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)));
        }
        // TODO: DRY (file names)
        public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotNull] string rootNamespace)
        {
            Check.NotEmpty(projectDir, nameof(projectDir));
            Check.NotEmpty(rootNamespace, nameof(rootNamespace));

            var files = new MigrationFiles();

            var modelSnapshot = _migrationsAssembly.ModelSnapshot;

            if (modelSnapshot == null)
            {
                throw new InvalidOperationException(CommandsStrings.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 (_historyRepository.GetAppliedMigrations().Any(
                            e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase)))
                    {
                        throw new InvalidOperationException(CommandsStrings.UnapplyMigration(migration.GetId()));
                    }

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

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

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

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

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

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

                _logger.Value.LogInformation(CommandsStrings.RevertingSnapshot);
                File.WriteAllText(modelSnapshotFile, modelSnapshotCode);
            }

            return(files);
        }
        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("EntityFramework.Core",                                                            copyLocal: true),
                        BuildReference.ByName("EntityFramework.Commands",                                                        copyLocal: true),
                        BuildReference.ByName("EntityFramework.Relational",                                                      copyLocal: true),
                        BuildReference.ByName("EntityFramework.Relational.Design",                                               copyLocal: true),
                        BuildReference.ByName("EntityFramework.MicrosoftSqlServer",                                              copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Caching.Memory",                                             copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection",                                        copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions",                           copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging",                                                    copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions",                                       copyLocal: true),
                        BuildReference.ByName("Microsoft.Extensions.OptionsModel",                                               copyLocal: true),
                        BuildReference.ByName("Remotion.Linq",                                                                   copyLocal: true)
                    },
                    Sources = { @"
                            using Microsoft.Data.Entity;
                            using Microsoft.Data.Entity.Infrastructure;
                            using Microsoft.Data.Entity.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"")
                                            .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 OperationExecutorWrapper(targetDir, build.TargetName, targetDir, "MyProject"))
                {
                    var ex = Assert.Throws <WrappedOperationException>(
                        () => executor.GetMigrations("MyContext"));

                    Assert.Equal(
                        CommandsStrings.MigrationsAssemblyMismatch(build.TargetName, "UnknownAssembly"),
                        ex.Message);
                }
            }
        }
Ejemplo n.º 27
0
        private IDictionary <Type, Func <DbContext> > FindContextTypes()
        {
            _logger.Value.LogDebug(CommandsStrings.LogFindingContexts);

            var startupAssembly = Assembly.Load(new AssemblyName(_startupAssemblyName));
            var contexts        = new Dictionary <Type, Func <DbContext> >();

            // Look for IDbContextFactory implementations
            var contextFactories = startupAssembly.GetConstructibleTypes()
                                   .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());
                }
            }

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

            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
            Assembly assembly;

            try
            {
                assembly = Assembly.Load(new AssemblyName(_assemblyName));
            }
            catch (Exception ex)
            {
                throw new OperationException(CommandsStrings.UnreferencedAssembly(_assemblyName, _startupAssemblyName), ex);
            }

            var types = startupAssembly.GetConstructibleTypes()
                        .Concat(assembly.GetConstructibleTypes())
                        .Select(i => i.AsType());
            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) ?? (() => (DbContext)Activator.CreateInstance(context)));
            }

            return(contexts);
        }