【问题标题】:Set a connectionString for a PostgreSQL database in Entity Framework outside the app.config在 app.config 之外的实体框架中为 PostgreSQL 数据库设置连接字符串
【发布时间】:2016-12-25 09:43:43
【问题描述】:

我有一个使用 PostgreSQL 构建的数据库,我通过 Entity Framework 6 访问它。

直到最近它通过app.config connectionString 顺利运行:

<connectionStrings>
    <add
        name="fancyName"
        connectionString="Host=localhost; user id=allCanSee; password=notSoSecret; database=notHidden"
        providerName="Npgsql" />
</connectionStrings>

我们的首席程序员对打开的 connectionString 不满意,因为我们安装软件的每台计算机都可以读取它。因此我们加密了所有内容,并将加密存储在app.config

现在我有一个新问题 - 我通过以下方式访问了我的数据库:

public class VersionContext
{
    public virtual DbSet<DatabaseNumber> DatabaseVersion { get; set; }

    public VersionContext() : base("name=fancyName")
    {
        System.Data.Entity.Database.SetInitializer<DatabaseContext>(null);
    }
}

但是由于我的app.config 不再包含连接字符串,我必须告诉数据库在哪里查找。

我目前的尝试是这样的:

public static class VersionContextConnection
{
    public static string GetConnectionString() //Accessable form everywhere
    {
        var providerName = "Npgsql";
        var databaseName = decryptedName;
        var userName = decryptedUserName;
        var password = decryptedPassword;
        var host = decryptedHostName
        var port = 5432;

        return $"Provider={providerName}; " + $"Server={host}; " + $"Port={port}; " + 
            $"User Id={userName}; " + $"Password={password}; " + $"Database={databaseName};";
    }
}

public class VersionContext : DbContext
{
    public virtual DbSet<DatabaseNumber> DatabaseVersion { get; set; }

    public VersionContext() : base(VersionContextConnection.GetConnectionString())
    {
        System.Data.Entity.Database.SetInitializer<DatabaseContext>(null);
    }
}

然后我将按如下方式访问它:

using (var context = new VersionContext())
{
    var entry = context.DatabaseVersion.FirstOrDefault();
    ...
}

但这给了System.Data一个例外,说Keyword not supported: 'provider'.

从 connectionString 中删除 provider 会产生另一个异常:Keyword not supported: 'port'.

从 connectionString 中删除 port 会产生来自 .Net SqlClient Data Provider 的第三个异常:Login failed for user 'secretSecret'.

那么 - 如果我的 connectionString 不是通过 :base(connectionString) 属性设置的,我该如何设置它?

【问题讨论】:

标签: c# entity-framework postgresql connection-string


【解决方案1】:

这就是我能够开始工作的......

    public static DbConnection GetDatabaseConnection()
    {
      
        NpgsqlConnectionStringBuilder npgsqlConnectionStringBuilder = new NpgsqlConnectionStringBuilder();
        npgsqlConnectionStringBuilder.Host = "localhost";
        npgsqlConnectionStringBuilder.Port = 5432;
        npgsqlConnectionStringBuilder.Database = "database";
        npgsqlConnectionStringBuilder.Username = "postgres";
        npgsqlConnectionStringBuilder.Password = "postgres";

        var conn = new NpgsqlConnectionFactory().CreateConnection(npgsqlConnectionStringBuilder.ConnectionString.ToString());
        return conn;
    }

【讨论】:

    【解决方案2】:

    this answer 出现了一个解决方案。

    app.config 包含提供者:

    <providers>
        <provider 
            invariantName="Npgsql" <!-- this is what we need -->
            type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
    </providers>
    

    通过让代码引用它,它可以创建连接:

    public static class VersionContextConnection
    {
        public static DbConnection GetDatabaseConnection()
        {
            var providerName = "Npgsql"; //Get this
            var databaseName = decryptedDatabaseName;
            var userName = decryptedUserName;
            var password = decryptedPassword;
            var host = decryptedHostName
            var port = 5432;
    
            //Insert it here
            var conn = DbProviderFactories.GetFactory(providerName).CreateConnection(); 
            conn.ConnectionString = $"Server={host}; " + $"Port={port}; " + 
                $"User Id={userName};" + $"Password={password};" + $"Database={databaseName};";
    
            return conn;
        }
    }
    

    这样设置DbContext

    public class VersionContext : DbContext
    {
        public virtual DbSet<DatabaseNumber> DatabaseVersion { get; set; }
    
        public VersionContext() : base(VersionContextConnection.GetDatabaseConnection(), true)
        {
            System.Data.Entity.Database.SetInitializer<DatabaseContext>(null); 
        }
    }
    

    然后调用你的代码:

    using (var context = new VersionContext())
    {
        var entry = context.DatabaseVersion.FirstOrDefault();
        ...
    }
    

    这样,您可以使用加密的登录参数填充您的app.config,检索它们,并将它们传递给您的DbContext

    【讨论】:

      【解决方案3】:

      您可以尝试使用 EntityConnectionStringBuilder:

      将你的静态方法修改为:

      public static string GetConnectionString() //Accessable form everywhere
      {
             var providerName = "Npgsql";
             var databaseName = decryptedName;
             var userName = decryptedUserName;
             var password = decryptedPassword;
             var host = decryptedHostName;
             var port = 5432;
      
             // Initializing the connection string builder for the provider
             SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
             sqlBuilder.ConnectionString = String.Format("Host={0};user id={1},password={2},database={3}",
             host, userName, password, databaseName);
      
             // Initialize the EntityConnectionStringBuilder.
             EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
             entityBuilder.Provider = providerName;
             entityBuilder.ProviderConnectionString = sqlBuilder.ToString();
      
             return entityBuilder.ToString();
      }
      

      并添加 using 语句:using System.Data.SqlClient;using System.Data.EntityClient; 顺便问一下,是否支持端口?在您首先显示的connectionString中,没有端口参数。

      【讨论】:

      • 或者,它应该是 server:port 吗?而不是服务器;端口?
      • 我前段时间试过,@Forlani,但它也导致了一个异常,它说它在entityBuilder 中丢失了metadata。我没有可提供的元数据,并且我尝试的方法导致了更多异常,这些异常没有使用 npgsql 进行连接。但是,我找到了解决方案(请参阅线程)。
      猜你喜欢
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-27
      • 2012-06-02
      • 1970-01-01
      相关资源
      最近更新 更多