Runtime compiling DbContext with EF core, missing reference for Migrator()

1k views Asked by At

I'm building an app that requires a EntityFrameWorkCore DbContext to be created runtime and then migrated, the code below compiles and runs if i don't use the dbContext.Database.Migrate() method, but if i do i get a diagnositcs error about missing a directive/reference.

error CS1061: 'DatabaseFacade' does not contain a definition for 'Migrate' and no accessible extension method 'Migrate' accepting a first argument of type 'DatabaseFacade' could be found (are you missing a using directive or an assembly reference?)

I also don't get any errors if i simply create a file with the code in my project. From what i can tell the "DatabaseFacade" is part of EntityFrameWorkcore.Infrastructure, which should be part if Microsoft.EntityFrameworkCore.

These are the references i'm including in the CSharpCompiler:

"System"
"System.Console"
"System.Runtime"
"System.Private.CoreLib"
"System.Linq"
"System.Data.Common"
"System.Data"
"System.Data.SqlClient"
"System.ComponentModel"
"Microsoft.EntityFrameworkCore"
"Microsoft.EntityFrameworkCore.SqlServer"
"netstandard"

I'm using Microsoft.CodeAnalysis to create a CSharpCompilation and then emit an assembly that i'm calling the main method in during runtime.

I've even tried to call the migrate() method with reflection to bypass intellisence, but GetMethod("Migrate") returns null, so it's obviously not there.

This is the code i am trying to compile and use runtime (Simplyfied):

using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using mothership_shared.Data;
using mothership_shared.Enums;
using mothership_shared.Interfaces;
using mothership_shared.Models;
using static mothership_shared.Attributes.PropertyCalculations;
using static mothership_shared.Attributes.PropertyTypes;
using static mothership_shared.Attributes.Settings;
using static mothership_shared.Data.SqlServiceClasses;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace mothership_shared.MigratorProgram
{
    public class Program
    {
        static void Main(string[] args)
        {
            SqlConnectionSettings sqlConnectionSettings = new SqlConnectionSettings()
            {
                ServerUrl = args[0],
                Catalog = args[1],
                User = args[2],
                Password = args[3],
            };
            var dbContext = new ApplicationDbContext(sqlConnectionSettings.AppConnection);
            ISql sqlService = new SqlService();
            var request = new DeleteMigrationHistory.Request()
            {
                ConnectionSettings = sqlConnectionSettings,
            };
            sqlService.DeleteMigrationHistory(request);
            dbContext.Database.Migrate();
        }
        public void Run(string[] args)
        {
            Main(args);
        }
        public class ApplicationDbContext : DbContext
        {
            private readonly string _connectionString;
            public ApplicationDbContext(string connectionString)
            {
                _connectionString = connectionString;
            }
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer(_connectionString);
            }

        public DbSet<SimpleEntity> SimpleEntity { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            var allTypes = Assembly.GetCallingAssembly().GetTypes();
            var EntityTypes = allTypes.Where(t => t.BaseType == typeof(BaseEntity));
            foreach (var t in EntityTypes)
            {
                var crud = t.GetCustomAttribute<CRUDAttribute>();
                var properties = t.GetProperties();
                foreach (var p in properties)
                {
                    IsObjectAttribute otm = p.GetCustomAttribute<IsObjectAttribute>();
                    if (otm != null)
                    {
                        if (crud.ClassType != ClassType.MTM)
                        {
                            modelBuilder.Entity(t)
                            .HasOne(p.PropertyType, p.Name)
                            .WithMany(otm.WithMany)
                            .OnDelete(otm.DeleteBehavior);
                        }
                        else
                        {
                            modelBuilder.Entity(t)
                            .HasOne(p.PropertyType, p.Name)
                            .WithMany(otm.WithMany)
                            .OnDelete(DeleteBehavior.Cascade);
                        }
                    };
                    IsTimeSpanAttribute ts = p.GetCustomAttribute<IsTimeSpanAttribute>();
                    if (ts != null)
                    {
                        modelBuilder.Entity(t)
                        .Property(p.Name)
                        .HasConversion(new TimeSpanToTicksConverter());
                    }
                }
            }
        }
    }
    [CRUDAttribute(ClassType.Referal)]
    [HeaderAttribute("Simple entity", "Simple entitys", 0)]
    [IconAttribute("ms-Icon--Document")]
    [MenuAttribute("Test menu")]
    [TooltipAttribute("This is a model that contains all simple propertytypes")]
    public class SimpleEntity : BaseEntity
    {
        [IsTextAttribute(false)]
        [HeaderAttribute("Text", "Texts", 0)]
        [PriorityAttribute(1)]
        [TooltipAttribute("This is a text property")]
        [IconAttribute("ms-Icon--Text")]
        [DefaultValueAttribute("This is the defaultvalue")]
        public string TextProperty { get; set; }
    }
}

}

1

There are 1 answers

1
Krzysztofz01 On BEST ANSWER

You need to install the extension Microsoft.EntityFrameworkCore.Tools, because Migrate is a part of it. If it still doesn't work, you can try dotnet restore, it often helps with extension related problems.