Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 6 Programmatically Connect to Postgres

I'm working on programmatically establishing a connection to PostgresSQL using Entity Framework 6. I have this class:

public class ClearspanDatabaseContext : DbContext

with this constructor:

public ClearspanDatabaseContext()
    : base(buildConnectionString())
{
}

Here's the static method that makes the connection string programmatically:

private static string buildConnectionString()
{
    RegisterDbProvider("Npgsql", ".Net Framework Data Provider for Postgresql", "Npgsql Data Provider", "Npgsql.NpgsqlFactory, Npgsql");
    EntityConnectionStringBuilder entityConnectionStringBuilder = new EntityConnectionStringBuilder();
    entityConnectionStringBuilder.Provider = "Npgsql";
    entityConnectionStringBuilder.ProviderConnectionString = "host=192.168.168.140;Port=5432;username=ClearspanDevLogin;password=*******;database=ClearspanWebServerDev";
    return entityConnectionStringBuilder.ToString();
}

And here's the method that registers Npgsql as a database provider, taken from this source:

public static bool RegisterDbProvider(string invariant, string description, string name, string type)
{
    try
    {
        DataSet ds = ConfigurationManager.GetSection("system.data") as DataSet;
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            if (row["InvariantName"].ToString() == invariant)
            {
                return true;
            }
        }
        ds.Tables[0].Rows.Add(name, description, invariant, type);
        return true;
    }
    catch
    {
    }
    return false;
}

This generates a string like this:

"provider=Npgsql;provider connection string=\"host=192.168.168.140;Port=5432;username=ClearspanDevLogin;password=********;database=ClearspanWebServerDev\""

But I get an ArgumentException:

Keyword not supported: 'provider'.

I think I am close to the programmatic connection, but am missing something small. What can I do to resolve this exception and properly setup this connection programmatically? No app.config answers, I'm working in a class library, which ignores app.config (see the comments of the accepted answer to this question). This program must remain this way because it is used as a plugin - it does not (nor should it) run on its own. Thanks in advance.

like image 441
Nick Gilbert Avatar asked Sep 04 '15 00:09

Nick Gilbert


People also ask

Can you use Entity Framework with PostgreSQL?

Furthermore, Entity Framework's design makes it particularly friendly for PostgreSQL developers. Entity Framework (EFCore) Core is a lighter weight and more flexible version that specifically enables . NET objects. It reduces the amount of data access code developers need to write, and offers higher-performance APIs.

How does Entity Framework connect to database?

During installation, the EntityFramework NuGet package checks which database server is available. The NuGet package will then update the configuration file by setting the default database server that Code First uses when creating a connection by convention.


1 Answers

Ok, here is working example for you which I verified is working. Using dummy code-first EF 6 model + custom DbConfiguration class:

public class Enrollment {
    public int EnrollmentID { get; set; }
    public int CourseID { get; set; }
    public int StudentID { get; set; }
}

[DbConfigurationType(typeof (NpgsqlConfiguration))]
public class SchoolContext : DbContext {
    public SchoolContext(string cs) : base(cs) {
    }

    public DbSet<Enrollment> Enrollments { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {

    }
}

class NpgsqlConfiguration : System.Data.Entity.DbConfiguration
{
    public NpgsqlConfiguration()
    {
        SetProviderServices("Npgsql", Npgsql.NpgsqlServices.Instance);
        SetProviderFactory("Npgsql", Npgsql.NpgsqlFactory.Instance);
        SetDefaultConnectionFactory(new Npgsql.NpgsqlConnectionFactory());
    }
}

Then, instead of your buildConnectionString(), just pass postgre connection string in constructor:

using (var ctx = new SchoolContext("host=192.168.168.40;port=5432;...")) {                
            Console.WriteLine(ctx.Enrollments.ToArray());
        } 

And that is all. Config file is completely empty during that, and it works.

like image 118
Evk Avatar answered Sep 22 '22 11:09

Evk