Entity Framework 6 Программно подключается к Postgres

Я работаю над программным установлением соединения с PostgresSQL с использованием Entity Framework 6. У меня есть этот класс:

public class ClearspanDatabaseContext : DbContext

с этим конструктором:

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

Здесь статический метод, который делает программную цепочку соединений:

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();
}

И вот метод, который регистрирует Npgsql в качестве поставщика базы данных, взятый из этого 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;
}

Это создает такую ​​строку:

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

Но я получаю ArgumentException:

Ключевое слово не поддерживается: "поставщик".

Я думаю, что я близок к программному соединению, но мне не хватает чего-то маленького. Что я могу сделать для устранения этого исключения и правильно настроить это соединение программно? Нет ответов app.config, я работаю в библиотеке классов, которая игнорирует app.config(см. Комментарии принятого ответа на этот question). Эта программа должна оставаться такой, потому что она используется как плагин - она ​​не работает (и не должна) запускаться сама по себе. Спасибо заранее.

Ответ 1

Хорошо, вот рабочий пример для вас, который я проверил, работает. Использование фиктивного кода - первая модель EF 6 + пользовательский класс DbConfiguration:

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());
    }
}

Затем вместо вашего buildConnectionString() просто передайте строку postgre connection в конструкторе:

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

И это все. Файл Config полностью пуст во время этого, и он работает.

Ответ 2

  • Вы просмотрели Code-Based Configuration? Создайте класс DbConfiguration с открытым конструктором без параметров в той же сборке, что и ваш DbContext

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

    Теперь я думаю, что DbContext должен использовать этот провайдер factory по умолчанию, и вы можете построить DbContext только с строкой соединения. Но если это в другой сборке, то у вас есть немного больше работы, но это можно найти в ссылке выше.

  • Потенциальная проблема с вышеупомянутым решением заключается в том, что любая конфигурация в файле конфигурации будет иметь приоритет, поэтому, возможно, было бы безопаснее использовать опцию, описанную в здесь:

    var conn = DbProviderFactories.GetFactory("MY_CONN_PROVIDER").CreateConnection();
    conn.ConnectionString = "MY_CONN_STR";
    
    new DbContext(conn, true);
    

    где ваш провайдер "Npgsql", который был зарегистрирован в RegisterDbProvider выше.

    Также см. https://msdn.microsoft.com/en-us/library/dd0w4a2z(v=vs.110).aspx