Docker 中的 Net Core 应用程序“不支持 LocalDB”而不使用本地数据库

Jan*_*nge 5 c# core docker .net-core asp.net-core

我有一个运行 SQL 数据库的 Net.Core 应用程序。连接字符串在环境变量中。

在本地 IIS 上,应用程序工作正常。

与 Docker-Container 相同的应用程序出现以下错误

失败:Microsoft.AspNetCore.Server.Kestrel[13] 连接 ID“0HLPO85V83VNO”,请求 ID“0HLPO85V83VNO:00000001”:应用程序引发了未处理的异常。System.PlatformNotSupportedException: 此平台不支持 LocalDB。
在 System.Data.SqlClient.SNI.LocalDB.GetLocalDBConnectionString(String localDbInstance)
在 System.Data.SqlClient.SNI.SNIProxy.GetLocalDBDataSource(String fullServerName, Boolean& error)

Docker 的环境变量: “DB_CONNECTION”:“Server=hc-XXX;Database=IB33DB-Core_XXX;User Id=sa;Password=XXX”

这是网络中的设置

网络信息

启动文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using ib.api_core.Data;
using Microsoft.EntityFrameworkCore;
using ib.api_core.Models;

namespace ib.api_core
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

            string dbConnection = Environment.GetEnvironmentVariable("DB_CONNECTION");
            Console.WriteLine("Env var DB Connection: "+dbConnection);

            //Verweis auf den Datenbank Kontext
            services.AddDbContext<ibContext>(options =>
                options.UseSqlServer(dbConnection));

            //Verweis auf den Datenbank Kontext
//            services.AddDbContext<ibContext>(options =>
//                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }


            //1. Alle Anfragen in der Konsole loggen
            app.UseMiddleware<RequestResponseLoggingMiddleware>();
            //2. Prüfe Login und Berechtigung der Anfrage
            app.UseMiddleware<AuthenticationMiddleware>();

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ibContext.cs

using System;
using Microsoft.EntityFrameworkCore;
namespace ib.api_core.Models
{
    public partial class ibContext : DbContext
    {

        public ibContext()
        {
        }

        public ibContext(DbContextOptions<ibContext> options)
            : base(options)
        {
        }

        public static ibContext GetContext()
        {
            var optionsBuilder = new DbContextOptionsBuilder<ibContext>();
            optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("DB_CONNECTION"));
            return new ibContext(optionsBuilder.Options);
        }

[...]  


        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(Environment.GetEnvironmentVariable("DB_CONNECTION"));
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
....
Run Code Online (Sandbox Code Playgroud)

Mar*_*kus 6

该错误消息意味着在某些时候,您的代码尝试使用为 LocalDB 配置的连接字符串访问数据库。我怀疑在您的 appsettings.json 中,有一个使用 LocalDB 的连接字符串,该字符串在某些时候使用过。

从代码示例中我找不到原因。也许某些代码绕过环境变量并从配置文件中读取连接字符串,或者容器运行旧版本的代码。


但是,在基于此示例的项目中,我能够覆盖容器中的连接字符串:

以下代码使用.NET Core 配置来获取连接字符串。这种方法的优点是您可以通过多种方式提供连接字符串,并在运行容器时覆盖它。

语境

示例中使用的上下文很简单:

public class BloggingContext : DbContext
{
    public BloggingContext(DbContextOptions<BloggingContext> options)
        : base(options)
    { }

    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

设置

startup.cs 中,使用 .NET Core 配置注册上下文并检索连接字符串:

var connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<BloggingContext>
    (options => options.UseSqlServer(connection));
Run Code Online (Sandbox Code Playgroud)

开发配置

对于开发,使用在appsettings.json 中配置的LocalDB

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;ConnectRetryCount=0"
  }
}
Run Code Online (Sandbox Code Playgroud)

覆盖容器的连接字符串

运行容器时,名为的环境变量ConnectionStrings:DefaultConnection会覆盖 appsettings 文件中的连接字符串。

为了调试,我在launchsettings.json 中插入了一个环境变量:

...
"Docker": {
  "commandName": "Docker",
  "launchBrowser": true,
  "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
  "environmentVariables": {
    "ASPNETCORE_URLS": "https://+:443;http://+:80",
    "ASPNETCORE_HTTPS_PORT": "44330",
    "ConnectionStrings:DefaultConnection": "Data Source=MY_IP\\MY_INSTANCE;Initial Catalog=TestDb;User Id=MY_USER;Password=MY_PWD"
  },
  "httpPort": 10000,
  "useSSL": true,
  "sslPort": 44330
}
...
Run Code Online (Sandbox Code Playgroud)

在 IIS Express 中运行时,使用appsettings.json 中的连接字符串,在容器中运行时,将按照环境变量中的配置访问主机上的 SQL Server 实例。