简体   繁体   中英

.net core 2 with ef core migrations with docker in development

I am working on a new project in which I will be hosting in a container so I wanted to develop with docker all along the process. However, it seems entity framework migrations run from the command line are not aware of the database service running.

My connection string:

"DefaultConnection": "Server=db;Database=Site;User=sa;Password=pwd;"

My docker compose:

version: '3'

services:
  db:
    image: microsoft/mssql-server-windows-express
    environment:
          sa_password: "pwd"
          ACCEPT_EULA: "Y"
        networks:
          - testnetwork

  site:
    image: site
    build:
      context: .
      dockerfile: Site\Dockerfile
    environment:
      - "Data:SqlServerConnectionString=Server=db;Database=HSRDC;User Id=sa;Password=pwd;MultipleActiveResultSets=true;App=site"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
          - "80"
        networks:
          - testnetwork
        depends_on:
          - db

    networks:
      testnetwork:
        external:
          name: nat

My startup with ensurecreated works:

public static void Initialize(CustomerDbContext context)
    {
        context.Database.EnsureCreated();

However, later in development I want to transition to migrations. When I try to update the database with dotnet ef database update eror:

System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible.

If I inspect the container and get the ip address and change my connection string to include the IP like:

"DefaultConnection": "Server=172.20.159.97;Database=HSRDC;User=sa;Password=SFMasc32*;"

The migrations will work fine.

However, this is clunky since I need to run to start the containers then stop and get the IP address and then modify they connection string with the IP and run again then migrate via the CLI.

The options I can see are specify an IP address in my compose file and hard code that IP in my connection string however in v3 it seems you can't specify an IP address .

Is there a way to make this more seamless to develop with docker in visual studio and work with migrations and docker?

If your IP is working and name is not. Then try giving full name of the DBServer eg DBServer.domain.xyz

You can implement IDesignTimeDbContextFactory<TContext> which is used by dotnet ef command line tools. Create a file called DesignTimeDbContextFactory in your asp.net core project (I placed it in the Data folder). The content should be:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDBContext>
{
    public MyDBContext CreateDbContext(string[] args)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
        var builder = new DbContextOptionsBuilder<MyDBContext>();
        var connectionString = configuration.GetConnectionString("migrationContextConnection");
        builder.UseSqlServer(connectionString);
        return new MyDBContext(builder.Options);
    }
}

And then add the following connection string to appsettings.json

  "ConnectionStrings": {
    "migrationContextConnection": "Server=localhost;Database=HSRDC;User=sa;Password=SFMasc32*;"
  }

Now you have to expose the port from your SQL docker container so that it's accessible by the host system. Add the following to your docker compose:

version: '3'

services:
  db:
    image: microsoft/mssql-server-windows-express
    environment:
      sa_password: "pwd"
      ACCEPT_EULA: "Y"
    networks:
      - testnetwork
    ports:
      - "1433:1433" 

You can now run dotnet ef database update and it'll work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM