从动态导入的 DLL 加载 EF Core 2 DbContext
Load EF Core 2 DbContext from dynamically imported DLL
我有一个 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());
}
}
我在反思方面非常缺乏经验 - 所以问题确实如此;
这是尝试实现此目的的最佳方法,还是我应该创建一个方法来调用 DLL 以 return 上下文?
如果没有,我该如何在没有上下文时传递 DbContextOptions 的实例?
旁注,这是一个 Asp.Net Core 2.0 MVC 项目。
编辑:当如下所示将一个空的 obj 数组传递给创建实例时,我得到了一个缺少方法的异常(未找到构造函数)
var dbContext = Activator.CreateInstance(defaultContext, new object[] { new object[0] }) as DbContext;
而如果我不传入第二个 obj 参数,我会得到相同的异常,但会出现消息 "No parameterless constructor defined for this object" 所以现在我很迷茫,因为显然有一个构造函数。
基本上问题是如何通过反射创建/获取 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);
我有一个 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());
}
}
我在反思方面非常缺乏经验 - 所以问题确实如此;
这是尝试实现此目的的最佳方法,还是我应该创建一个方法来调用 DLL 以 return 上下文?
如果没有,我该如何在没有上下文时传递 DbContextOptions 的实例?
旁注,这是一个 Asp.Net Core 2.0 MVC 项目。
编辑:当如下所示将一个空的 obj 数组传递给创建实例时,我得到了一个缺少方法的异常(未找到构造函数)
var dbContext = Activator.CreateInstance(defaultContext, new object[] { new object[0] }) as DbContext;
而如果我不传入第二个 obj 参数,我会得到相同的异常,但会出现消息 "No parameterless constructor defined for this object" 所以现在我很迷茫,因为显然有一个构造函数。
基本上问题是如何通过反射创建/获取 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);