【问题标题】:Socket error when connecting to In App MySQL in Azure App Service在 Azure 应用服务中连接到 In App MySQL 时出现套接字错误
【发布时间】:2020-01-19 15:44:39
【问题描述】:

我已将 ASP.NET Core 2.2 Web API 应用程序部署到 Azure 应用服务。我有一个 In App MySQL 作为应用服务的一部分。当我调用我的 API 时,我收到以下错误:

"ExtendedSocketException: An attempt was made to access a socket in a way forbidden by its access permissions 127.0.0.1:3306"

我四处寻找解决方案,发现:Access denied error while connecting to MySQL in App in Azure App Service

但是上面建议的修复并没有解决问题。

我还尝试了各种连接字符串,所有这些都导致相同的异常。这是我目前拥有的:

Server=localhost;Port=3306;Database=dbname;Uid=username;Pwd=password

所以,我的问题是:我应该怎么做才能让我的 ASP.NET Core API 连接到我的 In App MySql 数据库?

PS1:有很多文章描述了如何解决 Azure MySql DB 的连接问题(例如设置防火墙访问等),但不适用于 In App MySQL。

【问题讨论】:

  • 您是如何连接到数据库的?你是如何构造连接字符串的?你在使用环境变量localdb吗?
  • 是的,我在 appsettings.json 中有连接字符串。我现在没有使用环境变量。

标签: mysql asp.net azure asp.net-core


【解决方案1】:

首先,您不能通过appsettings.json 配置连接字符串。 Azure InApp MySQL 连接字符串通过环境变量自动配置:MYSQLCONNSTR_localdb

根据the docs

配置 API 具有针对四个连接字符串环境变量的特殊处理规则,这些变量涉及为应用环境配置 Azure 连接字符串。如果没有为 AddEnvironmentVariables 提供前缀,则会将具有表中所示前缀的环境变量加载到应用程序中。

简而言之,您需要通过以下方式获取预定义的ConnectionString

var conn = Configuration.GetConnectionString("localdb");

此外,Azure InApp MySQL ConnectionString 不是 Standard MySQL ConnectionString

Database=localdb;Server={host_like_127.0.0.1}:{port_like_52841};Uid={azure};Pwd={random}

换句话说,默认的ConnectionString 还没有准备好在 C# 中使用。

如何连接 InApp MySQL

为了将 InApp MySQL 与 ASP.NET Core 连接,我们需要在将其传递给 UseMySQL(conn) 之前对其进行规范化。这是我规范化默认 InApp ConnectionString 的脏代码:

private string NormalizeAzureInAppConnString(string raw) {
    string conn = string.Empty;
    try
    {
        var dict =
             raw.Split(';')
                 .Where(kvp => kvp.Contains('='))
                 .Select(kvp => kvp.Split(new char[] { '=' }, 2))
                 .ToDictionary(kvp => kvp[0].Trim(), kvp => kvp[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
        var ds = dict["Data Source"];
        var dsa = ds.Split(":");
        conn = $"Server={dsa[0]};Port={dsa[1]};Database={dict["Database"]};Uid={dict["User Id"]};Pwd={dict["Password"]};";
    }
    catch {
        throw new Exception("unexpected connection string: datasource is empty or null");
    }
    return conn;
}

然后你可以注册 DbContext 如下:

services.AddDbContext<AppDbContext>(options =>{
    var conn = Configuration.GetConnectionString("localdb");
    options.UseMySql( NormalizeAzureInAppConnString(conn) );
});

它现在应该可以工作了。

演示

【讨论】:

  • 非常感谢!我将在这里测试并更新。
  • itminus,非常感谢!它现在正在工作。套接字错误消失了。不过,只有一个观察结果。我的架构与 localdb 不同,但是当我使用 var conn = Configuration.GetConnectionString("mydb") 时,它无法连接,即它仅适用于 localdb。 MySql InApp 是否有任何强制要求 localdb 的限制?
  • @SirG 据我所知,localdb这个名字是由Azure环境变量MYSQLCONNSTR_localdb配置的,这个名字是不能改的。但作为一种解决方法,您可以使用 phpMyAdmin 来更改您的数据库。
猜你喜欢
  • 1970-01-01
  • 2014-10-29
  • 2019-06-25
  • 1970-01-01
  • 2017-07-08
  • 2012-06-25
  • 2020-01-22
  • 1970-01-01
  • 2016-09-12
相关资源
最近更新 更多