#c# #configuration #.net-core #entity-framework-core-2.2
#c# #конфигурация #.net-core #entity-framework-core-2.2
Вопрос:
Я использую Entity Framework Core в своем консольном приложении .NET Core. Я сохраняю свою строку подключения в App.config
файле и использую ConfigurationManager
в классе контекста для доступа к строке подключения.
Когда я хочу добавить новую миграцию в свой проект, я получаю следующую ошибку:
System.NullReferenceException: ссылка на объект не установлена для экземпляра объекта.
в EF_tut.Context.OnConfiguring(DbContextOptionsBuilder optionsBuilder) в C:..Context.cs:line 12
в Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
в Microsoft.EntityFrameworkCore.Внутренний.InternalAccessorExtensions.GetService[TService] (1 accessor)
фабрика IInfrastructure 1) в Microsoft.EntityFrameworkCore.Design.Внутренний.DbContextOperations.createContext(String ContextType) в Microsoft.EntityFrameworkCore.Design.Внутренний.MigrationsOperations.AddMigration(строковое имя, строковый outputDir, строковый ContextType) в Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(строковое имя, строковый outputDir, строковый ContextType) в Microsoft.EntityFrameworkCore.Design.OperationExecutor.Операционная база.<>c__DisplayClass3_0`1.b__0() в Microsoft.EntityFrameworkCore.Design.OperationExecutor.Операционная база.Выполнить (действие действия)
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
метод main, я получаю строку подключения, но когда я добавляю миграцию, я получаю ошибку ссылки Null.
Комментарии:
1. .Net core имеет другую систему конфигурации. Я не знаю, работает ли ConfigurationManager, но даже если это так, я предлагаю вам не использовать его.
2. сегодня я столкнулся с той же проблемой, я пытаюсь разделить классы домена, поэтому мне это нужно в отдельной библиотеке для подключения к azure sql и использования app.config для connectionstring . Использование ConfigurationManager. ConnectionStrings[«AzureTestDbContext»] . ConnectionString возвращает ‘System.NullReferenceException: ссылка на объект не установлена для экземпляра объекта.’. есть ли возможность использовать ConfigurationManager? мое временное решение также использовало жестко закодированную строку подключения.
Ответ №1:
Ядро EF создает экземпляр контекста БД во время разработки, например, Add-migration или Update-Database, для сбора сведений об объектах и их сопоставления.
Но App.config вашего проекта недоступен с помощью ConfigurationManager, поскольку EF core design-time — это другое приложение со своими собственными настройками приложения.
Я столкнулся с той же проблемой и нашел это решение, которое работает для меня:
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)
{
}
}
Определите фабрику контекста DB во время разработки, которая использует ConfigurationBuilder для извлечения строки подключения из App.config. Когда вы выполняете команду, такую как add-migration, ядро EF ищет класс внутри проекта, который реализует IDesignTimeDbContextFactory для получения экземпляра контекста БД, и если не найден, создает экземпляр контекста БД самостоятельно.
Вы можете найти больше о фабрике контекста DB во время разработки здесь:
Вам необходимо добавить пакеты Nuget Microsoft.Расширения.Конфигурация, Microsoft.Расширения.Конфигурация.Расширения файлов и Microsoft.Расширения.Конфигурация.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!");
}
}
Ответ №2:
Возможно, это немного обходной путь.. но это будет работать:
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"));
}
}
Ответ №3:
Я не совсем уверен, но я думаю, что вы должны исправить строку подключения. Попробуйте это в своем классе:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=YourPcName\YourSqlServerName;Database=YourDbName;Trusted_Connection=True;MultipleActiveResultSets=True;");
}
}
Комментарии:
1. Это работает, когда я жестко закодировал строку подключения в классе DbContext. Проблема заключается в использовании его через ConfigurationManager.
2. По правде говоря, я никогда не использовал Entity Framework в консольном приложении, только в Интернете. Разница между EF и EF-Core заключается в том, что EF-Core считывает строку подключения из файла json с именем appsettings.json, а не из Web.Config . Я думаю, что лучше всего было бы ознакомиться с официальной документацией и руководством здесь: entityframeworktutorial.net/efcore/… Удачи 🙂