Specifying database connection string for EntityFramework6.Npgsql - Code First - c#

I have an issue regarding the .NET postgreSQL provider package EntityFramework6.Npgsql. I have installed the following packages: EntityFramework 6.0.0, EntityFramework6.NpgSql 3.1.1, Npgsql 3.1.0.
Currently I have just started a WPF project so I'm using a simple standard DbContext and it looks like this:
public class TimetrackerDbContext : DbContext
{
public TimetrackerDbContext()
: base("name=DbConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("public");
base.OnModelCreating(modelBuilder);
}
public virtual DbSet<MyEntity> MyEntities { get; set; }
}
public class MyEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
Now in my App.config file I specify the connection string. I've been trying to use this connection:
<add name="DbConnection"
connectionString="User ID=xxx;Password=xxx;Host=xxx;Port=5432;Database=xxx;Pooling=true;"
providerName="System.Data.EntityClient" />
But when I run enable-migrations -contexttypename MyDbContext in the PM Console I get the following error:
Keyword not supported: 'user id'.
I tried specyfying the metadata, provider connection string but it also threw errors and it does not make much sense to use it in Code First. In case somebody it could be useful here's my whole App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<!--<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />-->
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
</providers>
</entityFramework>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Npgsql" publicKeyToken="5d8b90d52f46fda7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<connectionStrings>
<add name="DbConnection"
connectionString="User ID=xxx;Password=xxx;Host=xxx;Port=5432;Database=xxx;Pooling=true;"
providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>

The providerName of your connection string System.Data.EntityClient is for Database First (edmx) type connections where the actual provider is encoded in the connectionString value.
For Code First connections, the providerName should match the invariantName from the providers section. In your case, replace
providerName="System.Data.EntityClient"
to
providerName="Npgsql"

Related

'Option not supported' error when using SQL Server with MySQL

I'm trying to retrieve data from both MySQL and SQL Server on the same console application. I manage to retrieve data from MySQL, however when I trying to retrieve data from SQL Server, I got System.ArgumentException: 'Option not supported. Parameter name: multipleactiveresultsets' error.
The following is my app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<connectionStrings>
<add name="MySQLDb" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=sakila;uid=some_user;password=some_password"/>
<add name="SQLDb" providerName="System.Data.SqlClient" connectionString="data source=USER-PC\SQLEXPRESS;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"/>
</connectionStrings>
<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"/>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
</providers>
</entityFramework>
</configuration>
And my C#:
#region MySQL.
{
var dbContext = new MySQLDb();
var dbSet = dbContext.Set<Actor>();
var actors = dbSet.ToList();
}
#endregion
#region SQLServer.
{
var dbContext = new SQLDb();
var dbSet = dbContext.Set<User>();
var users = dbSet.ToList(); // <-- Throw exception.
}
#endregion
If I disable entityFramework section in app.config and MySQL code block in my C# code, I can retrieve data from SQL Server without any issue.
Version info
MySQL.Data.Entity 6.10.8
NET Framework 4.6.1
Any idea?
Update 1
Found out that the connection type for MySQLDb is MySql.Data.MySqlClient.MySqlConnection, so that works just fine. But when instantiating SQLDb, the connection type is still MySql.Data.MySqlClient.MySqlConnection instead of System.Data.SqlClient.SqlConnection. How should we fix this?
The issue is that we are using MySql.Data.Entity.MySqlEFConfiguration (in the app.config) which set the default connection factory to use MySqlConnectionFactory.
The solution is to use a custom DbConfiguration in place of MySql.Data.Entity.MySqlEFConfiguration to deter from setting the default connection factory.
public class MySQLDbConfiguration : DbConfiguration
{
public MySQLDbConfiguration()
{
SetProviderServices(MySqlProviderInvariantName.ProviderName, new MySqlProviderServices());
SetProviderFactory(MySqlProviderInvariantName.ProviderName, new MySqlClientFactory());
}
}
Declare the instance as readonly somewhere in the code,
private static readonly MySQLDbConfiguration DBConfig = new MySQLDbConfiguration();
and set the configuration PRIOR TO using any EF features
DbConfiguration.SetConfiguration(DBConfig);
And our app.config now becomes
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<connectionStrings>
<add name="MySQLDb" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=sakila;uid=some_user;password=some_password"/>
<add name="SQLDb" providerName="System.Data.SqlClient" connectionString="data source=USER-PC\SQLEXPRESS;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"/>
</connectionStrings>
</configuration>
If you're opt to use app.config instead of deriving a custom DbConfiguration, you can do the following
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- Alternative to custom DbConfiguration. -->
<configSections>
<section name = "entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<providers>
<provider invariantName = "MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"/>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant = "MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.10.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
</DbProviderFactories>
</system.data>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<connectionStrings>
<add name="MySQLDb" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=sakila;uid=some_user;password=some_password"/>
<add name="SQLDb" providerName="System.Data.SqlClient" connectionString="data source=USER-PC\SQLEXPRESS;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"/>
</connectionStrings>
</configuration>
If you are using asp net 5.0, install the Nuget found here, but first uninstall Mysql.data.

MySQL, EF6 and Database.CreateIfNotExists

I'm with problems with MySQL not creating the database using EF6. This code works fine in MSSQL Server (just changing the provider to "System.Data.SqlClient"):
public class MyDbContext : DbContext
{
public MyDbContext(string connectionString)
: base(GetConnection(connectionString),true)
{
Database.SetInitializer<MyDbContext>(new CreateDatabaseIfNotExists<MyDbContext>());
//Database.Initialize(true);
Database.CreateIfNotExists();
}
public DbSet<MyData> MyData { get; set; }
public static DbConnection GetConnection(string connectionString)
{
var factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
var connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
return connection;
}
}
The problem is in the line "Database.CreateIfNotExists();". It throws a NullReferenceException... Both "Database.Initialize(true);" and "Database.CreateIfNotExists()" throws the same error.
My connection string is:
Server=localhost;Database=MyDatabase;Uid=myUser;Pwd=myPassword;
The exact same code works fine on SQL Server. I even delete the database, and the SQL Server recreates it.
Doing some tests, using MySQL Shell, I manually created "MyDatabase" and the error does not happen, but the tables are not created.
Do I need some additional code in order to MySQL auto create the database and tables?
Other testing: I have added this code instead:
if (!Database.Exists())
{
Database.Create();
}
"Database.Exists()" works correctly, the problem is in ".Database.Create()". Really I think I'm missing something here.
* EDIT *
My App.Config. (I'm not using a connection string from app.config)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.12.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
</providers>
</entityFramework>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MySql.Data" publicKeyToken="c5687fc88969c44d" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.10.8.0" newVersion="6.10.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Found it! Reading the MySql docs here, I did that 2 changes:
(1) Added this second constructor to my DbContext:
// Constructor to use on a DbConnection that is already opened
public MyDbContext(DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
(2) With this new constructor, the code that works to generate the database is:
using (MySqlConnection connection = new MySqlConnection(myConnectionString))
{
using (MyDbContext contextDB = new MyDbContext(connection, false))
{
contextDB.Database.CreateIfNotExists();
}
}
I hope it can help someone!
Have you open the connection before to create the database?
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
//Do stuf with database...

Migrate database generated by entity framework to sqlserver

I made a application with database generated by entity framework(code first) and now I want to make my application working on other computer. I instaled sqlserver there and made all the tables in the database (I am working just with localhost database). Now I wanted to connect my database with application, I thought that all what I need to do is just change connection string. But I am not able to connect to my database.
Here is how looks my app.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<connectionStrings>
<add name="InzerceConnection" connectionString="Data source=VRBASPC\SQLEXPRESS;Initial Catalog=AdvertisingSystemDB;Trusted_Connection=true;MultipleActiveResultSets=true" />
<!--This is how my connection string works by default <add name="InzerceConnection" connectionString="Server=(localdb)\\MSSQLLocalDb;Database=Inzerce_Dev;Trusted_Connection=true;MultipleActiveResultSets=true" />-->
<!--<add name="InzerceConnection" connectionString="Server=localhost\SQLEXPRESS;Database=AdvertisingSystemDB;Trusted_Connection=true;MultipleActiveResultSets=true" />-->
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
I tried a lot of combination of connection string, but none worked.
I am not sure how to setup my config file to connect to database.
Thank you for any advice.
Sory for my english its not my native language.
In your context override the OnConfiguring method.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connstr = ConfigurationManager.ConnectionStrings["InzerceConnection"].ToString();
optionsBuilder.UseSqlServer(connstr);
}
Check in your database context.
Database context and name attributes should be the same.
For Example
public class DatabaseContext : DbContext
{
public DbSet<Content> Contents { get; set; }
public DbSet<Category> Categories { get; set; }
public DatabaseContext()
{
Database.SetInitializer(new MyInitializer());
}
}
ConnectionStrings in your app.config
<connectionStrings>
<add name="DatabaseContext" providerName="System.Data.SqlClient" connectionString="Data source=VRBASPC\SQLEXPRESS;Initial Catalog=AdvertisingSystemDB;Trusted_Connection=true;MultipleActiveResultSets=true" />
</connectionStrings>

Postgresql and Entity Framework

In my project I am trying to use Entity Framework along with PostgreSql. But I am not able to connect to my database. I am not getting any error, it just gets stuck. I think something is wrong with my app.config, but I am not able to find out what.
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql" />
<providers>
<provider invariantName="Npgsql"
type="Npgsql.NpgsqlServices, Npgsql.EntityFramework" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<add name="Npgsql Data Provider" invariant="Npgsql"
description="Data Provider for PostgreSQL"
type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories>
</system.data>
<connectionStrings>
<add name="Entities"
connectionString="server=localhost;user id=postgres;password=4321;database=postgis"
providerName="Npgsql" />
</connectionStrings>
</configuration>
DbContext:
public class Entities : DbContext
{
public Entities() : base("Entities")
{
}
//rest of the code
}
mycode.cs
using (var db = new Entities()) // when debug it stuck here and keep running
{
// some test code
}
EDIT:
I get the following error :
"The Entity Framework provider type 'Npgsql.NpgsqlServices, Npgsql.EntityFramework' registered in the application config file for the ADO.NET provider with invariant name 'Npgsql' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application.
The problem points to a wrong provider type or assembly name.
<entityFramework>
<defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql" />
<providers>
<provider invariantName="Npgsql"
type="Npgsql.NpgsqlServices, Npgsql.EntityFramework" />
</providers>
</entityFramework>
The assembly name is wrong. The assembly installed by the EntityFramework6.Npgsql package is EntityFramework6.Npgsql.dll. In fact, adding the package to a new project sets the correct provider line:
<providers>
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
</providers>

Entity Framework To A Remote Server (Connection String)

I have installed EF Version 6.1.3 on all my projects. I then created a model class, a context class, and installed a MSSQL database on my local computer (I did not have done anything else). Everything worked just perfectly (somehow it knew about my local database).
Model class:
public class Account
{
public int Id { get; set; }
public string Name{ get; set; }
}
DataContext class:
public class MyClassDataContext: DbContext
{
public DbSet<Account> Accounts{ get; set; }
}
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=xxxxxx" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
I then tried to move it to a remote database and it doesn't work. I tried everything.
What is the right approach, to get the job done?
EDIT:
I tried this connection string and nothing happens. The app still tries to connect with the local database.
<connectionStrings>
<add name="MyClassDataContext" connectionString="Data Source=MyRemoteServer;Initial Catalog=MyRemoteCatalog;Integrated Security=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
<configSections>
You need to create either make sure that your connections string's name is the fully qualified name of your context, or create an explicit default constructor for your context. Since you mentioned it in the comments, the link you provided isn't working for you because you're using code-first. Try this link instead.
Below is a fully functional console app that can demonstrate how it should work, along with the config file. This will use our local SQLServer installation, but not the SQLExpress. It should work fine for any remote database as well.
Note that in the previous app config that I had posted, I put the connection string section at the top. That is incorrect: configSections must be the first node.
namespace TestApp
{
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyClassDataContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var x = new MyClassDataContext())
{
x.Accounts.Add(new Account { Name = "Drew" });
x.SaveChanges();
var y = x.Accounts;
foreach (var s in y)
{
Console.WriteLine(s.Name);
}
}
Console.ReadKey();
}
}
}
The configuration file:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="ConsoleApplication4.MyClassDataContext" connectionString="Data Source=.;Initial Catalog=MyClass;Integrated Security=true" providerName="System.Data.SqlClient"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>

Categories

Resources