예제 #1
0
        private async Task WriteDbContext(NewDbContextTemplateModel dbContextTemplateModel,
                                          SyntaxTree newDbContextTree)
        {
            //ToDo: What's the best place to write the DbContext?
            var appBasePath = _environment.ApplicationBasePath;
            var outputPath  = Path.Combine(
                appBasePath,
                "Models",
                dbContextTemplateModel.DbContextTypeName + ".cs");

            if (File.Exists(outputPath))
            {
                // Odd case, a file exists with the same name as the DbContextTypeName but perhaps
                // the type defined in that file is different, what should we do in this case?
                // How likely is the above scenario?
                // Perhaps we can enumerate files with prefix and generate a safe name? For now, just throw.
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                                                                  "There was an error creating a DbContext, the file {0} already exists",
                                                                  outputPath));
            }

            var sourceText = await newDbContextTree.GetTextAsync();

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

            using (var fileStream = new FileStream(outputPath, FileMode.CreateNew, FileAccess.Write))
            {
                using (var streamWriter = new StreamWriter(stream: fileStream, encoding: Encoding.UTF8))
                {
                    sourceText.Write(streamWriter);
                }
            }
            _logger.LogMessage("Added DbContext : " + outputPath.Substring(appBasePath.Length));
        }
        public async Task <SyntaxTree> AddNewContext([NotNull] NewDbContextTemplateModel dbContextTemplateModel)
        {
            var templateName = "NewLocalDbContext.cshtml";
            var templatePath = _filesLocator.GetFilePath(templateName, TemplateFolders);

            Contract.Assert(File.Exists(templatePath));

            var templateContent = File.ReadAllText(templatePath);
            var templateResult  = await _templatingService.RunTemplateAsync(templateContent, dbContextTemplateModel);

            if (templateResult.ProcessingException != null)
            {
                throw new InvalidOperationException(string.Format(
                                                        "There was an error running the template {0}: {1}",
                                                        templatePath,
                                                        templateResult.ProcessingException.Message));
            }

            var newContextContent = templateResult.GeneratedText;

            var sourceText = SourceText.From(newContextContent);

            return(CSharpSyntaxTree.ParseText(sourceText));
        }
예제 #3
0
        public async Task <ModelMetadata> GetModelMetadata(string dbContextTypeName, ModelType modelTypeSymbol)
        {
            Type       dbContextType;
            var        dbContextSymbols = _modelTypesLocator.GetType(dbContextTypeName).ToList();
            var        isNewDbContext   = false;
            SyntaxTree newDbContextTree = null;
            NewDbContextTemplateModel dbContextTemplateModel = null;

            if (dbContextSymbols.Count == 0)
            {
                isNewDbContext = true;
                await ValidateEFSqlServerDependency();

                _logger.LogMessage("Generating a new DbContext class " + dbContextTypeName);
                dbContextTemplateModel = new NewDbContextTemplateModel(dbContextTypeName, modelTypeSymbol);
                newDbContextTree       = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel);

                _logger.LogMessage("Attempting to compile the application in memory with the added DbContext");
                var projectCompilation = _libraryManager.GetProject(_environment).Compilation;
                var newAssemblyName    = projectCompilation.AssemblyName + _counter++;
                var newCompilation     = projectCompilation.AddSyntaxTrees(newDbContextTree).WithAssemblyName(newAssemblyName);

                var result = CommonUtilities.GetAssemblyFromCompilation(_loader, newCompilation);
                if (result.Success)
                {
                    dbContextType = result.Assembly.GetType(dbContextTypeName);
                    if (dbContextType == null)
                    {
                        throw new InvalidOperationException("There was an error creating a DbContext, there was no type returned after compiling the new assembly successfully");
                    }
                }
                else
                {
                    throw new InvalidOperationException("There was an error creating a DbContext :" + string.Join("\n", result.ErrorMessages));
                }
            }
            else
            {
                dbContextType = _libraryManager.GetReflectionType(_environment, dbContextTypeName);

                if (dbContextType == null)
                {
                    throw new InvalidOperationException("Could not get the reflection type for DbContext : " + dbContextTypeName);
                }
            }

            var modelTypeName = modelTypeSymbol.FullName;
            var modelType     = _libraryManager.GetReflectionType(_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);

            // Write the DbContext if getting the model metadata is successful
            if (isNewDbContext)
            {
                await WriteDbContext(dbContextTemplateModel, newDbContextTree);
            }

            return(metadata);
        }
        public async Task<ModelMetadata> GetModelMetadata(string dbContextTypeName, ModelType modelTypeSymbol)
        {
            Type dbContextType;
            var dbContextSymbols = _modelTypesLocator.GetType(dbContextTypeName).ToList();
            var isNewDbContext = false;
            SyntaxTree newDbContextTree = null;
            NewDbContextTemplateModel dbContextTemplateModel = null;

            if (dbContextSymbols.Count == 0)
            {
                isNewDbContext = true;
                await ValidateEFSqlServerDependency();

                _logger.LogMessage("Generating a new DbContext class " + dbContextTypeName);
                dbContextTemplateModel = new NewDbContextTemplateModel(dbContextTypeName, modelTypeSymbol);
                newDbContextTree = await _dbContextEditorServices.AddNewContext(dbContextTemplateModel);

                _logger.LogMessage("Attempting to compile the application in memory with the added DbContext");
                var projectCompilation = _libraryManager.GetProject(_environment).Compilation;
                var newAssemblyName = projectCompilation.AssemblyName + _counter++;
                var newCompilation = projectCompilation.AddSyntaxTrees(newDbContextTree).WithAssemblyName(newAssemblyName);

                var result = CommonUtilities.GetAssemblyFromCompilation(_loader, newCompilation);
                if (result.Success)
                {
                    dbContextType = result.Assembly.GetType(dbContextTypeName);
                    if (dbContextType == null)
                    {
                        throw new InvalidOperationException("There was an error creating a DbContext, there was no type returned after compiling the new assembly successfully");
                    }
                }
                else
                {
                    throw new InvalidOperationException("There was an error creating a DbContext :" + string.Join("\n", result.ErrorMessages));
                }
            }
            else
            {
                dbContextType = _libraryManager.GetReflectionType(_environment, dbContextTypeName);

                if (dbContextType == null)
                {
                    throw new InvalidOperationException("Could not get the reflection type for DbContext : " + dbContextTypeName);
                }
            }

            var modelTypeName = modelTypeSymbol.FullName;
            var modelType = _libraryManager.GetReflectionType(_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);

            // Write the DbContext if getting the model metadata is successful
            if (isNewDbContext)
            {
                await WriteDbContext(dbContextTemplateModel, newDbContextTree);
            }

            return metadata;
        }
        private async Task WriteDbContext(NewDbContextTemplateModel dbContextTemplateModel,
            SyntaxTree newDbContextTree)
        {
            //ToDo: What's the best place to write the DbContext?
            var appBasePath = _environment.ApplicationBasePath;
            var outputPath = Path.Combine(
                appBasePath,
                "Models",
                dbContextTemplateModel.DbContextTypeName + ".cs");

            if (File.Exists(outputPath))
            {
                // Odd case, a file exists with the same name as the DbContextTypeName but perhaps
                // the type defined in that file is different, what should we do in this case?
                // How likely is the above scenario?
                // Perhaps we can enumerate files with prefix and generate a safe name? For now, just throw.
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                    "There was an error creating a DbContext, the file {0} already exists",
                    outputPath));
            }

            var sourceText = await newDbContextTree.GetTextAsync();

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

            using (var fileStream = new FileStream(outputPath, FileMode.CreateNew, FileAccess.Write))
            {
                using (var streamWriter = new StreamWriter(stream: fileStream, encoding: Encoding.UTF8))
                {
                    sourceText.Write(streamWriter);
                }
            }
            _logger.LogMessage("Added DbContext : " + outputPath.Substring(appBasePath.Length));
        }