我在.NET Core控制台应用程序中使用Entity Framework Core。我将连接字符串存储在App.config
文件中,并在上下文类中使用ConfigurationManager
来访问连接字符串。
当我想向项目中添加新的迁移时,出现以下错误:
System.NullReferenceException:对象引用未设置为对象的实例。
在C:\ .. \ Context.cs:line 12中的EF_tut.Context.OnConfiguring(DbContextOptionsBuilder optionsBuilder)中
在Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
在Microsoft.EntityFrameworkCore.Internal.InternalAccessorExtensions.GetService [TService](IInfrastructure1 accessor)
1工厂) 在Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) 在Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(字符串名称,字符串outputDir,字符串contextType) 在Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(字符串名称,字符串outputDir,字符串contextType) 在Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase。<> c__DisplayClass3_0`1.b__0() 在Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(操作动作)处
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func对象引用未设置为对象的实例。
这是我的App.config
文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="EfTutDb"
connectionString="Data Source=.;Initial Catalog=EF_tut;Integrated Security=True;"/>
</connectionStrings>
</configuration>
这是我的上下文类:
class Context : DbContext
{
public DbSet<Student> Students { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["EfTutDb"].ConnectionString); // Line 12.
}
}
当我尝试在主要方法中使用ConfigurationManger
获取连接字符串时,我得到了连接字符串,但是当我添加迁移时,我得到了Null Reference错误。
答案 0 :(得分:1)
我不太确定,但是我认为您必须修复连接字符串。 在您的课程中尝试以下方法:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=YourPcName\\YourSqlServerName;Database=YourDbName;Trusted_Connection=True;MultipleActiveResultSets=True;");
}
}
答案 1 :(得分:1)
也许这是一种解决方法,但是它可以工作:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddXmlFile("App.config")
.Build();
optionsBuilder.UseSqlServer(configuration.GetValue<string>("connectionStrings:add:EfTutDb:connectionString"));
}
}
答案 2 :(得分:0)
EF核心在设计时实例化数据库上下文,例如Add-migration或Update-Database,以收集有关实体的详细信息并映射它们。
但是您的项目的App.config无法使用ConfigurationManager进行访问,因为EF核心设计时是具有自己的应用程序设置的另一个应用程序。
我遇到了同样的问题,并找到了适合我的解决方案:
App.config:
<configuration>
<connectionStrings>
<add name="Default"
connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=EFCoreSample;Integrated Security=SSPI"/>
</connectionStrings>
向数据库上下文添加一个构造函数,该上下文将接收DbContextOptions并将其传递给基本构造函数:
public class EFCoreSampleDbContext : DbContext
{
public EFCoreSampleDbContext(DbContextOptions options)
: base(options)
{
}
}
定义一个设计时数据库上下文工厂,该工厂使用ConfigurationBuilder从App.config中检索连接字符串。当您运行诸如add-migration之类的命令时,EF Core会在项目内部寻找一个实现IDesignTimeDbContextFactory的类,以接收数据库上下文的实例,如果找不到,则由其实例化Db上下文。
您可以在此处找到有关设计时数据库上下文工厂的更多信息:
您需要为此添加Nuget包Microsoft.Extensions.Configuration,Microsoft.Extensions.Configuration.FileExtensions和Microsoft.Extensions.Configuration.Xml。另外,将App.config文件的“复制到输出目录”属性设置为“始终复制”。
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<EFCoreSampleDbContext>
{
public EFCoreSampleDbContext CreateDbContext(string[] args)
{
var optionsBuilder =
new DbContextOptionsBuilder<EFCoreSampleDbContext>();
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddXmlFile("App.config")
.Build();
string connectionString;
if (configuration
.Providers
.FirstOrDefault()
.TryGet("connectionStrings:add:Default:connectionString",
out connectionString))
{
optionsBuilder.UseSqlServer(connectionString);
var dbContext =
new EFCoreSampleDbContext(optionsBuilder.Options);
return dbContext;
}
else
throw new Exception("The design-time connection string not found!");
}
}