这里的解决方案是“解析” Heroku 提供的DATABASE_URL环境变量的内容,并使用它来构建 Npgsql 期望的格式的连接字符串。
要获得快速而肮脏的解决方案,您可以按照以下解决方案进行操作:.net core - database url parser。
对于我的项目,我决定更进一步,并为此创建了一个基于其他连接字符串构建器(用于 MS SQL、Mongo 等)的类:
public enum SslMode
{
Require,
Disable,
Prefer
}
public class PostgreSqlConnectionStringBuilder : DbConnectionStringBuilder
{
private string _database;
private string _host;
private string _password;
private bool _pooling;
private int _port;
private string _username;
private bool _trustServerCertificate;
private SslMode _sslMode;
public PostgreSqlConnectionStringBuilder(string uriString)
{
ParseUri(uriString);
}
public string Database
{
get => _database;
set
{
base["database"] = value;
_database = value;
}
}
public string Host
{
get => _host;
set
{
base["host"] = value;
_host = value;
}
}
public string Password
{
get => _password;
set
{
base["password"] = value;
_password = value;
}
}
public bool Pooling
{
get => _pooling;
set
{
base["pooling"] = value;
_pooling = value;
}
}
public int Port
{
get => _port;
set
{
base["port"] = value;
_port = value;
}
}
public string Username
{
get => _username;
set
{
base["username"] = value;
_username = value;
}
}
public bool TrustServerCertificate
{
get => _trustServerCertificate;
set
{
base["trust server certificate"] = value;
_trustServerCertificate= value;
}
}
public SslMode SslMode
{
get => _sslMode;
set
{
base["ssl mode"] = value.ToString();
_sslMode = value;
}
}
public override object this[string keyword]
{
get
{
if (keyword == null) throw new ArgumentNullException(nameof(keyword));
return base[keyword.ToLower()];
}
set
{
if (keyword == null) throw new ArgumentNullException(nameof(keyword));
switch (keyword.ToLower())
{
case "host":
Host = (string) value;
break;
case "port":
Port = Convert.ToInt32(value);
break;
case "database":
Database = (string) value;
break;
case "username":
Username = (string) value;
break;
case "password":
Password = (string) value;
break;
case "pooling":
Pooling = Convert.ToBoolean(value);
break;
case "trust server certificate":
TrustServerCertificate = Convert.ToBoolean(value);
break;
case "sslmode":
SslMode = (SslMode) value;
break;
default:
throw new ArgumentException(string.Format("Invalid keyword '{0}'.", keyword));
}
}
}
public override bool ContainsKey(string keyword)
{
return base.ContainsKey(keyword.ToLower());
}
private void ParseUri(string uriString)
{
var isUri = Uri.TryCreate(uriString, UriKind.Absolute, out var uri);
if (!isUri) throw new FormatException(string.Format("'{0}' is not a valid URI.", uriString));
Host = uri.Host;
Port = uri.Port;
Database = uri.LocalPath.Substring(1);
Username = uri.UserInfo.Split(':')[0];
Password = uri.UserInfo.Split(':')[1];
}
}
然后,在我的Startup.cs 中,在Configuration 方法中,我有:
var builder = new PostgreSqlConnectionStringBuilder(Configuration["DATABASE_URL"])
{
Pooling = true,
TrustServerCertificate = true,
SslMode = SslMode.Require
};
services.AddEntityFrameworkNpgsql()
.AddDbContext<TTRDbContext>(options => options.UseNpgsql(builder.ConnectionString));
如果您从 Heroku 网络外部(例如本地环境)访问数据库,则需要添加 SSL Mode 和 Trust Server Certificate。
希望对你有帮助