9

我在我的 .NET Core 控制台应用程序中使用 Entity Framework Core。我将连接字符串存储在App.config文件中并ConfigurationManager在上下文类中使用来访问连接字符串。

当我想向我的项目添加新迁移时,出现以下错误:

System.NullReferenceException:对象引用未设置为对象的实例。

在 EF_tut.Context.OnConfiguring(DbContextOptionsBuilder optionsBuilder) 在 C:\..\Context.cs:line 12
在 Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
在 Microsoft.EntityFrameworkCore.Internal.InternalAccessorExtensions.GetService[TService](IInfrastructure1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func
1 工厂)在 Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType) 在 Microsoft.EntityFrameworkCore.Design.OperationExecutor 的 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)。 Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0() 中的 AddMigrationImpl(String name, String outputDir, String contextType) Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

你调用的对象是空的。

这是我的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在 main 方法中使用获取连接字符串时,我得到了连接字符串,但是当我添加迁移时,我得到空引用错误。

4

3 回答 3

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"));
    }
}
于 2020-04-14T10:33:47.490 回答
0

The EF Core instantiates the DB context at design-times such as Add-migration or Update-Database, to gather details about the entities and map them.

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

But the App.config of your project is not accessible using the ConfigurationManager, since the EF core design-time is another application with its own application settings.

I faced the same problem and found this solution which works for me:

App.config:

<configuration>
<connectionStrings>
    <add name="Default" 
        connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=EFCoreSample;Integrated Security=SSPI"/>
</connectionStrings>

Add a constructor to the DB context which receives a DbContextOptions and passes it to the base constructor:

public class EFCoreSampleDbContext : DbContext
{
    public EFCoreSampleDbContext(DbContextOptions options)
        : base(options)
    {

    }
}

Define a design-time DB context factory, which uses ConfigurationBuilder to retrieve the connection string from the App.config. When you run a command such as add-migration, EF Core looks for a class inside the project which implements the IDesignTimeDbContextFactory to receive an instance of the DB context, and if not found, instantiates the Db context by itself.

You can find more about the design-time DB context factory here:

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

You need to add Nuget packages Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.FileExtensions, and Microsoft.Extensions.Configuration.Xml for this one. Also, set the "Copy to Output Directory" property of the App.config file to "Copy always".

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!");
    }
}
于 2020-12-09T17:06:46.487 回答
-1

我不太确定,但我认为您必须修复连接字符串。在你的课堂上试试这个:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer("Server=YourPcName\\YourSqlServerName;Database=YourDbName;Trusted_Connection=True;MultipleActiveResultSets=True;");
        }
    }
于 2019-04-12T23:44:10.910 回答