c# - 从动态导入的 DLL 加载 EF Core 2 DbContext

标签 c# entity-framework-core asp.net-core-2.0 system.reflection ef-core-2.0

我有一个 DbContext 我需要从 DLL 动态加载,因为 Db 上下文会改变并且需要在应用程序运行时进行编辑,但是我似乎无法创建此上下文的实例,因为我似乎需要传递上下文选项。这段代码在下面。

Assembly reporting = Assembly.LoadFile(pathString);

        var defaultContext = reporting.GetType("Reporting.DefaultContext");
        var dbContext = Activator.CreateInstance(defaultContext, new
 object[] { /*need to pass in the contructor here*/ }) as DbContext;

而且我的编译上下文很标准,下面是一个修改版本供引用

public class DefaultContext : DbContext
{
    public DefaultContext(DbContextOptions<DefaultContext> options)
        : base(options)
    { }

    public virtual DbSet<Student> Students { get; set; }
    public virtual DbSet<Course> Courses { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Student>().ToTable("Students ", "core")
            .AllProperties().ForEach(x => x.IsRequired());

        modelBuilder.Entity<Course>().ToTable("Courses", "core")
            .AllProperties().ForEach(x => x.IsRequired());
    }
}

我在反射(reflection)方面非常缺乏经验 - 所以问题确实如此;

这是尝试实现此目标的最佳方法,还是我应该创建一个方法来调用 DLL 以返回上下文?

如果不是,当我没有上下文时,我该如何处理 DbContextOptions 的实例?

旁注,这是一个 Asp.Net Core 2.0 MVC 项目。

编辑:当如下所示将一个空的 obj 数组传递给创建实例时,我得到了一个缺少方法的异常(未找到构造函数)

var dbContext = Activator.CreateInstance(defaultContext, new object[] { new object[0] }) as DbContext;

然而,如果我不传递第二个 obj 参数,我会得到相同的异常,但会出现消息“没有为此对象定义无参数构造函数”,所以现在我很迷茫,因为显然有一个构造函数。

最佳答案

基本上问题是如何创建/获取DbContextOptions<DefaultContext>通过反射实例。您可以通过首先通过 MakeGenericType 构造一个通用类型来做到这一点然后将该类型用作 Activator.CreateInstance 的参数.

所以有

var dbContextType = reporting.GetType("Reporting.DefaultContext");

像这样:

var optionsType = typeof(DbContextOptions<>).MakeGenericType(dbContextType);
var options = (DbContextOptions)Activator.CreateInstance(optionsType);
var dbContext = (DbContext)Activator.CreateInstance(dbContextType, options);

但是,DbContextOptions<TDbContext> options 的整个目的构造函数参数是允许从外部配置数据库上下文(如数据库提供程序、连接字符串等),而不是在内部自行配置 OnModelConfiguring ,在这种情况下,您的派生数据库上下文将只具有无参数构造函数。

因此最好创建DbContextOptionsBuilder<DefaultContext例如,使用 Fluent APi 配置它,然后传递 Options属性(这是预期的 DbContextOptions<DefaultContext 类型)到 DefaultContext构造函数。例如

var optionsBuilderType = typeof(DbContextOptionsBuilder<>).MakeGenericType(dbContextType);
var optionsBuilder = (DbContextOptionsBuilder)Activator.CreateInstance(optionsBuilderType);

string connectionString = ...;
optionsBuilder.UseSqlServer(connectionString);

var dbContext = (DbContext)Activator.CreateInstance(dbContextType, optionsBuilder.Options);

关于c# - 从动态导入的 DLL 加载 EF Core 2 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50601844/

相关文章:

c# - MySQL中两个表的递归语句

c# - 屏蔽元素\属性值,使用Linq

c# - 将密码添加到 Xamarin 表单中的 Sqlite 文件

c# - 将 Entity Framework Core 的 CosmosDB 提供程序与 Azure 表结合使用时出错

c# - Dot Net Core 2.0 多重cookie

C# WinForms,在运行时动态添加用户控件并且控件不可见?

c# - 无法访问的代码在哪里?

c# - 通过 LINQ 加载嵌套属性

asp.net - 使用 CustomUrlHelper 覆盖 UrlHelper - ASP.NET CORE 2.0

.net - Razor 页面可以放在除 Pages 之外的任何其他目录中吗?