public async Task<ContextProcessingResult> GetModelMetadata(string dbContextFullTypeName, ModelType modelTypeSymbol) { Type dbContextType; SyntaxTree dbContextSyntaxTree = null; EditSyntaxTreeResult startUpEditResult = new EditSyntaxTreeResult() { Edited = false }; ContextProcessingStatus state = ContextProcessingStatus.ContextAvailable; var dbContextSymbols = _modelTypesLocator.GetType(dbContextFullTypeName).ToList(); var startupType = _modelTypesLocator.GetType("Startup").FirstOrDefault(); if (dbContextSymbols.Count == 0) { await ValidateEFSqlServerDependency(); // Create a new Context _logger.LogMessage("Generating a new DbContext class " + dbContextFullTypeName); var dbContextTemplateModel = new NewDbContextTemplateModel(dbContextFullTypeName, modelTypeSymbol); dbContextSyntaxTree = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel); state = ContextProcessingStatus.ContextAdded; // Edit startup class to register the context using DI if (startupType != null) { startUpEditResult = _dbContextEditorServices.EditStartupForNewContext(startupType, dbContextTemplateModel.DbContextTypeName, dbContextTemplateModel.DbContextNamespace, dataBaseName: dbContextTemplateModel.DbContextTypeName + "-" + Guid.NewGuid().ToString()); } if (!startUpEditResult.Edited) { state = ContextProcessingStatus.ContextAddedButRequiresConfig; // The created context would anyway fail to fetch metadata with a crypic message // It's better to throw with a meaningful message throw new InvalidOperationException("Scaffolding failed to edit Startup class to register the new Context using Dependency Injection." + "Make sure there is a Startup class and a ConfigureServices method and Configuration property in it"); } dbContextType = CompileAndGetDbContext(dbContextFullTypeName, c => { c = c.AddSyntaxTrees(dbContextSyntaxTree); if (startUpEditResult.Edited) { c = c.ReplaceSyntaxTree(startUpEditResult.OldTree, startUpEditResult.NewTree); } return c; }); // Add file information dbContextSyntaxTree = dbContextSyntaxTree.WithFilePath(GetPathForNewContext(dbContextTemplateModel.DbContextTypeName)); } else { var addResult = _dbContextEditorServices.AddModelToContext(dbContextSymbols.First(), modelTypeSymbol); if (addResult.Edited) { state = ContextProcessingStatus.ContextEdited; dbContextSyntaxTree = addResult.NewTree; dbContextType = CompileAndGetDbContext(dbContextFullTypeName, c => { var oldTree = c.SyntaxTrees.FirstOrDefault(t => t.FilePath == addResult.OldTree.FilePath); Debug.Assert(oldTree != null); return c.ReplaceSyntaxTree(oldTree, addResult.NewTree); }); } else { dbContextType = _libraryExporter.GetReflectionType(_libraryManager, _environment, dbContextFullTypeName); if (dbContextType == null) { throw new InvalidOperationException("Could not get the reflection type for DbContext : " + dbContextFullTypeName); } } } var modelTypeName = modelTypeSymbol.FullName; var modelType = _libraryExporter.GetReflectionType(_libraryManager, _environment, modelTypeName); if (modelType == null) { throw new InvalidOperationException("Could not get the reflection type for Model : " + modelTypeName); } _logger.LogMessage("Attempting to figure out the EntityFramework metadata for the model and DbContext"); var metadata = GetModelMetadata(dbContextType, modelType, startupType); // Write the DbContext/Startup if getting the model metadata is successful if (dbContextSyntaxTree != null) { PersistSyntaxTree(dbContextSyntaxTree); if (state == ContextProcessingStatus.ContextAdded || state == ContextProcessingStatus.ContextAddedButRequiresConfig) { _logger.LogMessage("Added DbContext : " + dbContextSyntaxTree.FilePath.Substring(_environment.ApplicationBasePath.Length)); if (state != ContextProcessingStatus.ContextAddedButRequiresConfig) { PersistSyntaxTree(startUpEditResult.NewTree); } else { _logger.LogMessage("However there may be additional steps required for the generted code to work properly, refer to documentation <forward_link>."); } } } return new ContextProcessingResult() { ContextProcessingStatus = state, ModelMetadata = metadata }; }
public async Task <ContextProcessingResult> GetModelMetadata(string dbContextFullTypeName, ModelType modelTypeSymbol) { Type dbContextType; SyntaxTree dbContextSyntaxTree = null; EditSyntaxTreeResult startUpEditResult = new EditSyntaxTreeResult() { Edited = false }; ContextProcessingStatus state = ContextProcessingStatus.ContextAvailable; var dbContextSymbols = _modelTypesLocator.GetType(dbContextFullTypeName).ToList(); var startupType = _modelTypesLocator.GetType("Startup").FirstOrDefault(); if (dbContextSymbols.Count == 0) { await ValidateEFSqlServerDependency(); // Create a new Context _logger.LogMessage("Generating a new DbContext class " + dbContextFullTypeName); var dbContextTemplateModel = new NewDbContextTemplateModel(dbContextFullTypeName, modelTypeSymbol); dbContextSyntaxTree = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel); state = ContextProcessingStatus.ContextAdded; // Edit startup class to register the context using DI if (startupType != null) { startUpEditResult = _dbContextEditorServices.EditStartupForNewContext(startupType, dbContextTemplateModel.DbContextTypeName, dbContextTemplateModel.DbContextNamespace, dataBaseName: dbContextTemplateModel.DbContextTypeName + "-" + Guid.NewGuid().ToString()); } if (!startUpEditResult.Edited) { state = ContextProcessingStatus.ContextAddedButRequiresConfig; // The created context would anyway fail to fetch metadata with a crypic message // It's better to throw with a meaningful message throw new InvalidOperationException("Scaffolding failed to edit Startup class to register the new Context using Dependency Injection." + "Make sure there is a Startup class and a ConfigureServices method and Configuration property in it"); } dbContextType = CompileAndGetDbContext(dbContextFullTypeName, c => { c = c.AddSyntaxTrees(dbContextSyntaxTree); if (startUpEditResult.Edited) { c = c.ReplaceSyntaxTree(startUpEditResult.OldTree, startUpEditResult.NewTree); } return(c); }); // Add file information dbContextSyntaxTree = dbContextSyntaxTree.WithFilePath(GetPathForNewContext(dbContextTemplateModel.DbContextTypeName)); } else { var addResult = _dbContextEditorServices.AddModelToContext(dbContextSymbols.First(), modelTypeSymbol); if (addResult.Edited) { state = ContextProcessingStatus.ContextEdited; dbContextSyntaxTree = addResult.NewTree; dbContextType = CompileAndGetDbContext(dbContextFullTypeName, c => { var oldTree = c.SyntaxTrees.FirstOrDefault(t => t.FilePath == addResult.OldTree.FilePath); Debug.Assert(oldTree != null); return(c.ReplaceSyntaxTree(oldTree, addResult.NewTree)); }); } else { dbContextType = _libraryExporter.GetReflectionType(_libraryManager, _environment, dbContextFullTypeName); if (dbContextType == null) { throw new InvalidOperationException("Could not get the reflection type for DbContext : " + dbContextFullTypeName); } } } var modelTypeName = modelTypeSymbol.FullName; var modelType = _libraryExporter.GetReflectionType(_libraryManager, _environment, modelTypeName); if (modelType == null) { throw new InvalidOperationException("Could not get the reflection type for Model : " + modelTypeName); } _logger.LogMessage("Attempting to figure out the EntityFramework metadata for the model and DbContext"); var metadata = GetModelMetadata(dbContextType, modelType, startupType); // Write the DbContext/Startup if getting the model metadata is successful if (dbContextSyntaxTree != null) { PersistSyntaxTree(dbContextSyntaxTree); if (state == ContextProcessingStatus.ContextAdded || state == ContextProcessingStatus.ContextAddedButRequiresConfig) { _logger.LogMessage("Added DbContext : " + dbContextSyntaxTree.FilePath.Substring(_environment.ApplicationBasePath.Length)); if (state != ContextProcessingStatus.ContextAddedButRequiresConfig) { PersistSyntaxTree(startUpEditResult.NewTree); } else { _logger.LogMessage("However there may be additional steps required for the generted code to work properly, refer to documentation <forward_link>."); } } } return(new ContextProcessingResult() { ContextProcessingStatus = state, ModelMetadata = metadata }); }