使用Npgsql和Entity Framework Code First无法在PostgreSQL中创建数据库

6

我试图使用Entity Framework和PostgreSQL设置我的应用程序,但是遇到了问题。我已经通过NuGet添加了Npgsql,并在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: 数据库"withoomph"不存在

当设置数据库时,我正确地设置了数据库初始化器:

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

所以当我尝试使用DbContext时,它应该只是简单地创建数据库,对吧?我不明白,整个早上都在绞尽脑汁!

3个回答

9

很遗憾,截至目前,Npgsql没有自动的代码优先模式下的架构创建功能。

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

更新(2016):Npgsql 3现在实现了代码优先的数据库创建。请确保配置正确的连接工厂来使用NpgsqlConnection,可以通过代码或XML设置进行配置,并使用适当的连接字符串


1
终于,在上网搜寻了很久之后,我终于找到了确切的原因!谢谢,至少现在我知道是要使用pgsql进行数据库优先,还是使用其他方式进行代码优先 :-) - jcvandan
3
请问如何解决这个问题?我使用NuGet安装了Npgsql.Entityframework(v2.2.5),同时也安装了EF6和Npgsql 2.2.5。但是在使用(DataAccessContext db = new DataAccessContext(dbConnection))时,出现了异常"dbo.xyz不可用"。下面是出现异常的代码:using (DataAccessContext db = new DataAccessContext(dbConnection)) { IObjectContextAdapter adapter = (IObjectContextAdapter)db; string script = adapter.ObjectContext.CreateDatabaseScript(); // 异常:"CreateDatabaseScript is not supported by the provider." } - Offler
我有一点困惑。您的意思是说一旦数据库存在,EF会根据代码中的实体创建表格吗?因为我也无法让npgsql创建表格。 - Tuncay Göncüoğlu
@AlexMazzariol,你有使用EF6和npgsql创建数据库的示例吗?你有代码片段吗? - FrancoTampieri
我相信任何带有典型DbSet的示例DbContext都可以工作。目前,我有半打.NET业务应用程序(Web应用程序)托管在Linux上,并使用PostgreSQL作为RDBMS。您是否遇到了特定的问题?如果是这种情况,请开另一个问题 :) - Alex Mazzariol
显示剩余3条评论

4

毫不意外,由于您的数据库withoomph尚未创建,因此您无法使用涉及Database=withoomph;的连接字符串。

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

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

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


好的,我会试一下。这让我感到困惑,因为这与我尝试使用EF的所有其他类型的SQL数据库的行为不同,而且关于如何做这件事的信息并不多。我会回报的。 - jcvandan

2

除了 MVP 的回答外,这是我用来创建数据库的代码片段。在初始化 EF 之前需要运行它。 所以,诀窍在于将数据库名称暂时切换为“postgres”,这是在原始安装后保证存在的。

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上吗?谢谢! - gdubs
我通常会有一个单独的控制台来执行这些操作。你可以将它放在global.asax中的应用程序启动中,但是你需要先检查数据库是否存在,否则每次启动应用程序时它都会重新创建你的数据库 :) - Robin van der Knaap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接