添加迁移时用于提取数据库连接字符串时,ConfigurationManager返回null

时间:2019-04-12 20:46:55

标签: c# configuration .net-core entity-framework-core-2.2

我在.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](IInfrastructure 1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func
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(操作动作)处

     

对象引用未设置为对象的实例。

这是我的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错误。

3 个答案:

答案 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,以收集有关实体的详细信息并映射它们。

https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/#design-time-dbcontext-configuration

但是您的项目的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上下文。

您可以在此处找到有关设计时数据库上下文工厂的更多信息:

https://docs.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli#from-a-design-time-factory[2]

您需要为此添加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!");
    }
}