【问题标题】:Unable to create database in PostreSQL using Npgsql and Entity Framework code first无法首先使用 Npgsql 和实体框架代码在 PostgreSQL 中创建数据库
【发布时间】:2013-01-01 00:06:17
【问题描述】:

我正在尝试设置我的应用程序以将 Entity Framework 与 PostgreSQL 一起使用,但我遇到了一个问题。我已经通过 nuget 添加了Npqsql,并将以下提供程序工厂添加到web.config

<system.data>
    <DbProviderFactories>
        <add name="Npgsql Data Provider" 
           invariant="Npgsql" 
           description=".Net Framework Data Provider for Postgresql Server" 
           type="Npgsql.NpgsqlFactory, Npgsql, 
                 Version=2.0.12.0, Culture=neutral, 
                 PublicKeyToken=5d8b90d52f46fda7" />
    </DbProviderFactories>
  </system.data>

带连接字符串:

    <add name="MyDb" providerName="Npgsql" 
connectionString="Server=localhost;Port=5432;Database=withoomph;User ID=postgres;Password=******;enlist=true" />

它似乎可以很好地连接到数据库,但是当我尝试对数据库执行任何操作时,我得到以下异常:

FATAL: 3D000: database "withoomph" does not exist

当数据库设置如下时,我正在正确设置数据库初始化程序:

static MyDB()
{
    Database.SetInitializer<MyDB>(new CreateDatabaseIfNotExists<MyDB>());
}

所以当我尝试用我的DbContext 做任何事情时,它应该只是简单地创建数据库,对吗?我不明白,整个上午都在拔头发!

【问题讨论】:

    标签: c# entity-framework postgresql npgsql


    【解决方案1】:

    毫不奇怪,由于您的数据库withoomph 尚未创建,您应该无法在提到Database=withoomph; 的地方使用连接字符串。

    您可以使用createdbpsql 手动创建此数据库,或者临时更改连接字符串以使用Database=postgres;

    这应该可以工作,因为在所有最新的 PostgreSQL 版本上,数据库 postgres 保证在 vanilla 安装后存在,并且应该仅用于此目的 - 获取初始经过身份验证的连接以创建另一个数据库并在您的应用程序中发出 CREATE DATABASE withoomph;

    但是,在您的新数据库创建后,您应该立即断开与postgres 的连接,连接到新的withoomph 并正常继续。

    【讨论】:

    • 好的,我试试看。它让我感到震惊,因为这与我尝试使用 EF 的所有其他类型的 SQL db 的行为不同,也没有太多关于如何执行此操作的信息。我会回来报告的。
    【解决方案2】:

    不幸的是,Npgsql 没有(截至目前)自动模式创建代码优先。

    您可以先创建数据库,然后连接到它。

    更新 (2016):Npgsql 3 现在实现数据库创建代码优先。确保通过代码或 XML 设置配置正确的连接工厂以使用 NpgsqlConnections,并使用适当的 Connection String

    【讨论】:

    • 天知道在互联网上搜索了多少之后,我终于得到了发生这种情况的确切原因!谢谢,至少现在我知道它要么是使用 pgsql 的 DB-first,要么是使用其他东西的代码优先 :-)
    • 在我回答近 2 年后添加评论...新的 Npgsql 2.2.0 版本包括对迁移和使用 EF6 的 codefirst 的支持
    • 请问怎么做?我使用 nuget 安装 Npgswl.Entityframework (v 2.2.5)。这也安装了 EF6 和 npqsql 2.2.5 。我有一个例外,即 dbo.xyz 不可用。使用 (DataAccessContext db = new DataAccessContext(dbConnection)) { IObjectContextAdapter 适配器 = (IObjectContextAdapter)db;字符串脚本 = adapter.ObjectContext.CreateDatabaseScript(); -> 例外:“提供者不支持 CreateDatabaseScript。”
    • 我有点困惑。您是说一旦数据库存在,EF 实际上会首先从代码中的实体创建表吗?因为我也无法让 npgsql 创建表。
    • 使用来自 NuGet 的当前 EntityFramework (6.1.3) 和 EntityFramework6.Npgsql (3.0.5) 以及适当的用户权限(在我的情况下是经典超级用户),我从一个空的 postgresql 设置。在 2013 年首次添加此答案时,这是不可能的。
    【解决方案3】:

    除了mvp的回答,这里有一段我​​用来创建数据库的代码sn-p。您需要在初始化 EF 之前运行它。 因此,诀窍是将数据库名称临时切换为“postgres”,在安装 vanilla 后保证存在。

    public void CreateDatabase(string connectionString)
    {
        var builder = new NpgsqlConnectionStringBuilder(connectionString);
        var databaseName = builder.Database; // REMEMBER ORIGINAL DB NAME
        builder.Database = "postgres"; // TEMPORARILY USE POSTGRES DATABASE
    
        // Create connection to database server
        using (var connection = new NpgsqlConnection(builder.ConnectionString))
        {
            connection.Open();
    
            // Create database
            var createCommand = connection.CreateCommand();
            createCommand.CommandText = string.Format(@"CREATE DATABASE ""{0}"" ENCODING = 'UTF8'", databaseName);
            createCommand.ExecuteNonQuery();
    
            connection.Close();
        }
    }
    

    【讨论】:

    • 嘿,我也有同样的问题。想知道你在哪里触发了这个方法?在初始化器上?我按照说明将 web.config 更改为“postgres”,但现在它正在检查 postgres 数据库并且不会触发我的初始化程序。我应该把它放在 global.asax.cs 上吗?谢谢!
    • 我通常有一个单独的控制台来执行这些操作。您可以将它放在应用程序启动中的 global.asax 中,但是您应该先检查数据库是否存在,否则每次启动应用程序时它都会重新创建您的数据库:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    相关资源
    最近更新 更多