Используйте Entity Framework для подключения к базе данных MySQL, работающей в контейнере Docker

#asp.net-mvc #entity-framework #docker #asp.net-core #docker-compose

#asp.net-mvc #entity-framework #docker #asp.net-core #docker-compose

Вопрос:

Я начал изучать ASP.NET Core MVC и я пытаюсь создать приложение, которое использует базу данных. Я хотел интегрировать ORM, поэтому я выбрал Entity Framework Core.

Я подготовил проект, следуя этому руководству. Я успешно выполнил миграцию с помощью

 dotnet ef migrations add Initial --context ReceptionistContext
  

но я не могу обновить базу данных, работающую внутри моего контейнера Docker. Я хотел выполнить это действие с помощью

 dotnet ef database update --context ReceptionistContext
  

Я получаю эту ошибку:

информация: Microsoft.EntityFrameworkCore.Инфраструктура[10403]
Ядро Entity Framework 2.2.3-обслуживание-35854 инициализировал ‘Recept Context’ с помощью поставщика ‘Microsoft.EntityFrameworkCore.SQLServer’ с параметрами: Нет

System.Data.SqlClient.SQLException (0x80131904): при установлении соединения с SQL Server произошла ошибка, связанная с сетью или конкретным экземпляром. Сервер не был найден или был недоступен. Убедитесь, что имя экземпляра указано правильно и что SQL Server настроен для разрешения удаленных подключений. (поставщик: TCP Provider, ошибка: 35 — Было обнаружено внутреннее исключение)

System.Net.Internals.SocketExceptionFactory ExtendedSocketException (00000005, 6): нет такого устройства или адреса

в System.Net.Dns.InternalGetHostByName(строковое имя хоста)
в System.Net.Dns.GetHostAddresses(строка hostNameOrAddress) в System.Data.SqlClient.SNI.SNITCPHandle.Подключитесь (строковое имя сервера, порт Int32, тайм-аут TimeSpan) к System.Data.SqlClient.SNI.SNITCPHandle..ctor(Строковое имя сервера, порт Int32, timerExpire Int64, объект callbackObject, логическая параллель) к System.Data.SqlClient.SqlInternalConnectionTds..ctor (идентификатор DbConnectionPoolIdentity, SqlConnectionString ConnectionOptions, SqlCredential credential, Object providerInfo, строка NewPassword, SecureString newSecurePassword, логическое перенаправление Userinstance, SqlConnectionString userConnectionOptions, переподключение сессионных данных, логическая обработка applyTransientFaultHandling, Доступ к строке открыт) в System.Data.SqlClient.SqlConnectionFactory.Создайте соединение (DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, dbconnectionconnectionconnection Owning, DbConnectionOptions userOptions) в System.Data.База поставщиков.DbConnectionFactory.Создайте PooledConnection (пул DbConnectionPool, объект DbConnection owningObject, параметры DbConnectionOptions, пул DbConnectionPoolKey, пользовательские опции DbConnectionOptions) в системе.данные.База поставщиков.DbConnectionPool.Создайте объект (DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) в System.Data.База поставщиков.DbConnectionPool.Запрос пользователя (DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) в System.Data.База поставщиков.DbConnectionPool.Попробуйте getConnection (DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, логическое значение allowCreate, логическое значение onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternalamp; connection) в System.Data.База поставщиков.DbConnectionPool.Попробуйте установить соединение (DbConnection owningObject, TaskCompletionSource 1 retry, DbConnectionOptions userOptions, DbConnectionInternalamp; connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource
1 повтор, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternalamp; connection) в System.Data.База поставщиков.DbConnectionInternal.Попробуйте открыть внутреннее подключение (DbConnection outerConnection, DbConnectionFactory ConnectionFactory, TaskCompletionSource 1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource
1 повтор, DbConnectionOptions userOptions) в System.Data.SqlClient.SqlConnection.Попробуйте открыть (TaskCompletionSource 1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0
2.b__0(DbContext c, TState s) в Microsoft.EntityFrameworkCore.SQLServer.Хранение.Внутренняя стратегия.SqlServerExecutionStrategy.Выполните[TState,TResult] (успешно проверено состояние TState, функция 3 operation, Func 3) в Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Выполните[TState,TResult] (IExecutionStrategy strategy, функция 2 operation, Func 2 проверена успешно, состояние TState) в Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Выполните[TState,TResult] (стратегия IExecutionStrategy, состояние TState, операция Func`2) в Microsoft.EntityFrameworkCore.SQLServer.Хранение.Internal.SqlServerDatabaseCreator.Существует (логическая повторная попытка не существует) в Microsoft.EntityFrameworkCore.SQLServer.Хранение.Internal.SqlServerDatabaseCreator.Существует () в Microsoft.EntityFrameworkCore.Миграции.HistoryRepository.Exists() в Microsoft.EntityFrameworkCore.Миграции.Внутренний.Мигратор.Миграция (String TargetMigration) в Microsoft.EntityFrameworkCore.Design.Внутренний.Операции миграции.Обновленная база данных (String TargetMigration, String ContextType) в Microsoft.EntityFrameworkCore.Design.OperationExecutor.Обновленная база данных.<> c__DisplayClass0_1.<.ctor>b__0() в Microsoft.EntityFrameworkCore.Design.OperationExecutor.Операционная база.Выполнить (Действие action)
ClientConnectionId: 00000000-0000-0000-0000000000000000
При установлении соединения с SQL Server произошла ошибка, связанная с сетью или конкретным экземпляром. Сервер не был найден или был недоступен. Убедитесь, что имя экземпляра указано правильно и что SQL Server настроен для разрешения удаленных подключений. (поставщик: TCP Provider, ошибка: 35 — Было обнаружено внутреннее исключение)

docker-compose.yml :

 version: "3"
services:
    db:
      # get the image
      image: mysql:5.7
      # define the container name
      container_name: "mysql_database"
      # set up the envinronment
      environment:
        MYSQL_DATABASE: 'hospital_management'
        # Set up a user
        MYSQL_USER: 'app'
        # Set up the password
        MYSQL_PASSWORD: 'password'
        # Password for root access
        MYSQL_ROOT_PASSWORD: 'root'
      # persists the data outside the container
      volumes:
        - ./data:/var/lib/mysql
      # map the ports host:container
      ports:
        - "3308:3306"
  

appsettings.json :

 {
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ReceptionistContext": "Data Source=127.0.0.1:3608"
  }
}
  

Наконец, app.csproj :

 <Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>


  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SQLite" Version="2.2.3" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
    <PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.15" />
  </ItemGroup>
  

P.S. Я позаботился о том, чтобы к базе данных можно было получить доступ за пределами базы данных, и я также использовал MySQL workbench для подключения к ней. Я также убедился, что контейнер был запущен, когда я пытался выполнить обновление.

Спасибо!

Комментарии:

1. В вашей строке подключения не указана база данных для подключения, а также имя пользователя и пароль для использования.

2. Я подозревал, что это может быть проблемой, но я действительно не знал, что добавить. Это моя первая встреча с .net. Не могли бы вы, пожалуйста, добавить дополнительные сведения о том, как добавить их в настройки?

Ответ №1:

Существует несколько проблем с вашим кодом / конфигурацией.

Первое, что вы получаете исключение, в котором говорится, что ваш контекст использует Microsoft.EntityFrameworkCore.SqlServer поставщика. Это означает, что вы пытаетесь подключиться к серверу Microsoft SQL вместо MySQL.

Причина в том, что в вашем классе context у вас, вероятно, есть строка, подобная этой:

 options.UseSqlServer(Configuration.GetConnectionString("ReceptionistContext")));
  

однако вам нужен вызов config, который сообщает, что вы хотите использовать MySQL:

 options.UseMySql(Configuration.GetConnectionString("ReceptionistContext")));
  

Следующее, что в настоящее время вы не указываете базу данных, имя пользователя или пароль в строке подключения:

 "ReceptionistContext": "Data Source=127.0.0.1:3608"
  

и вы пытаетесь подключиться к порту 3608, но в вашем файле docker compose вы сопоставляете порт 3308

   ports:
    - "3308:3306"
  

итак, попробуйте следующее для вашей строки подключения

 "ReceptionistContext": "Server=127.0.0.1;Port=3308;Database=hospital_management;Uid=app;Pwd=password"
  

это должно соответствовать вашей конфигурации docker compose:

 Environment:
    MYSQL_DATABASE: 'hospital_management'
    # Set up a user
    MYSQL_USER: 'app'
    # Set up the password
    MYSQL_PASSWORD: 'password'
  

Комментарии:

1. Большое вам спасибо, сэр. Я отредактировал строки конфигурации, но я все еще получаю сообщение «Произошла одна или несколько ошибок. (Не удается подключиться ни к одному из указанных хостов MySQL.)’. Контейнер запущен, и я могу успешно подключиться к нему с помощью workbench по адресу ‘127.0.0.1:3308’

2. Я использовал неправильный формат в строке подключения. Я отредактировал свой пост и исправил ошибку, чтобы соответствовать этому connectionstrings.com/mysql-connector-net-mysqlconnection

3. «Источником данных» должно быть «Сервер» в строке подключения.

4. Спасибо @ChrisPratt. Я только что отредактировал свой ответ и изменил источник данных на сервер

Ответ №2:

Как все упоминалось выше, у меня не было определенных строк подключения. Таким образом, я добавил эти строки в appsettings.json :

 "AllowedHosts": "*",
  "ConnectionStrings": {
    "HMContext": "Server=127.0.0.1;Port=3308;Database=hospital_management;Uid=app;Pwd=password"
  }
  

Другая проблема заключалась в том, что я использовал UseSql insted of UseMySql в Startup.cs .

У меня все еще были проблемы. Это произошло из-за того, что строки подключения не соответствовали подписи UseMySql (приведенные выше строки верны).

После всего этого приложение подключилось к базе данных docker, но у меня все еще была ошибка, связанная с отсутствием таблицы миграций. Похоже, это ошибка, но ее можно устранить, запустив следующий скрипт:

 CREATE TABLE `__EFMigrationsHistory` ( `MigrationId` nvarchar(150) NOT NULL, `ProductVersion` nvarchar(32) NOT NULL, PRIMARY KEY (`MigrationId`) );