LLBLGEN Pro v3.5 and NPGSQL v3.1.8: ArgumentException

Posts   
 
    
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 10-Oct-2016 12:56:25   

Hello, I run LLBLGEN using LLBLGenPro_NET40.exe on Windows 7 64-bit. Trying to test a connection to PostgreSQL 9.2 server in "Add relational model data from db" option I have got the following exception:

Exception message:

Exception type: ArgumentException Keyword not supported: password=...;encoding Parameter name: keyword

LLBLGen Pro version 3.5. Build January 17th, 2013 -----[Core exception]-------------------- in Npgsql.NpgsqlConnectionStringBuilder.GetProperty(String keyword) in Npgsql.NpgsqlConnectionStringBuilder.set_Item(String keyword, Object value) in System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(String value) in Npgsql.NpgsqlConnection.<>c__DisplayClass33_0.<set_ConnectionString>b__0(String s) in System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory) in Npgsql.NpgsqlConnection.set_ConnectionString(String value) in SD.LLBLGen.Pro.DBDriverCore.DBDriverBase.CreateConnection() in SD.LLBLGen.Pro.Gui.Controls.WizardPages.MetaDataRetrievalWizard_Step_ConnectionData.TestConnectionData(Boolean showSuccess)

Npgsql driver is installed and registered in GAC. Machine.config contains the entry referring to the driver so I suppose it's properly installed. Could you please advice what can be wrong?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 10-Oct-2016 16:18:55   

This seems like an issue that was reported and solved. Could you please make sure you are using the latest release of v.3.5?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 10-Oct-2016 16:48:39   

This is a problem with npgsql v3, which has different features and it is not backwards compatible. We fixed in v4.2 (and up) but not in v3.5. You're advised to use v2.x of npgsql if you're using llblgen pro v3.x or earlier, as its driver isn't updated with the necessary code for types and meta-data retrieval for npgsql v3.

Frans Bouma | Lead developer LLBLGen Pro
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 11-Oct-2016 08:13:09   

@Walaa: I had found similar thread, before I published my question, but referring to LLBLGEN Pro v4.2

@Otis: Thank you for the advice! I will try with v2.2.5

etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 11-Oct-2016 13:16:35   

It seems I still have the problem. Details:

  • I have downloaded and installed the application again to be sure I have the current
  • I have downloaded NPGSQL 2.0.4.0 - same version as the one in LLBLGenPro.exe.config - registered in GAC and uncomented "add name" section for PostgreSQL in LLBLGenPro.exe.config
  • I have checked that the LLBLGenPro.exe.config entry is the only (commented similar entries in machine.configs) loaded for LLBLGenPro When I try to connect again I obtain a very similar error (see my first post in the thread):

Exception message:

Exception type: ArgumentException key=value argument incorrect in ConnectionString Parameter name: password=...;encoding

If I remove the password I have:

Exception message:

Exception type: NpgsqlException FATAL: 28000: LDAP authentication failed for user "<my user name>"

Exception information.

LLBLGen Pro version: v3.5. Build: January 17th, 2013

Exception details:

Message: FATAL: 28000: LDAP authentication failed for user "<my user name>" Source: Npgsql Stack trace: in Npgsql.NpgsqlState.<ProcessBackendResponses>d__0.MoveNext() in Npgsql.NpgsqlState.ProcessAndDiscardBackendResponses(NpgsqlConnector context) in Npgsql.NpgsqlConnector.Open() in Npgsql.NpgsqlConnectorPool.GetPooledConnector(NpgsqlConnection Connection) in Npgsql.NpgsqlConnectorPool.RequestPooledConnectorInternal(NpgsqlConnection Connection) in Npgsql.NpgsqlConnectorPool.RequestConnector(NpgsqlConnection Connection) in Npgsql.NpgsqlConnection.Open() in SD.LLBLGen.Pro.Gui.Controls.WizardPages.MetaDataRetrievalWizard_Step_ConnectionData.TestConnectionData(Boolean showSuccess)

Inner exception: <null>

Any advice if I may please?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Oct-2016 15:17:22   

what encoding do you specify in the connection dialog? Just use the default, as the others aren't implemented by Npgsql as it turned out (in v3, no-one really knew)

Frans Bouma | Lead developer LLBLGen Pro
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 12-Oct-2016 08:14:19   

ASCII. Once I tried UNICODE but there was no difference - the same error message.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-Oct-2016 09:53:47   

I think the v3 npgsql is still used. did you install that through its installer? That registers itself in the machine.config file. windows\microsoft.net\framework64\v4.0.30319\config\machine.config likely contains the registration. (there are more machine.config files, one for each .net version installed and for 32bit and 64bit. Normally if you start the designer on 64bit windows, it will use .net 4.x, 64bit)

Frans Bouma | Lead developer LLBLGen Pro
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 12-Oct-2016 10:55:50   

Well, earlier I only commented the v3 entries in machine.configs (I know there are four - for .NET 2.0, 4.0 and 32/64 bit architecture). Now I have uninstalled NPGSQL 3.1.8 and checked by gacutil.exe /l that there is only:

Npgsql, Version=2.0.4.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7, processorArchitecture=MSIL

in GAC. All the Npgsql sections in machine.configs are commented and the only entry:

<add name="PostgreSql Client Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for PostgreSql" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.4.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"/>

exists in LLBLGenPro.exe.config Unfortunately the error remains the same:

Exception message:

Exception type: ArgumentException key=value argument incorrect in ConnectionString Parameter name: password=...;encoding

with the same stack trace as before. BTW I am trying to "Add Relational Model Data from a Database" to the existing project with one MySQL db in Catalog Explorer but it doesn't matter, I suppose.

Update: does the password content matter - I mean special characters like "=!@-_"? I can connect to PostgreSQL server via pgAdmin or Visual Studio with the same user/password but maybe the password spoils the connection string for LLBLGen.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-Oct-2016 19:02:14   

the password is embedded in the connection string, and I think it goes wrong there, but not sure. We'll have to check.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 13-Oct-2016 14:50:11   

The password is embedded into the query string, and we escape ';' so that can't be it. We can connect without problems with the llblgen pro 3.5 driver. So as we can't reproduce it, could you do the following please?

  • download the sourcecode package for v3.5 from the website: my account -> downloads -> 3.5 -> Extras. There you'll find the sourcecode archive.
  • unpack it and load the drivers sln file into vs.net. Remove the other driver projects besides the postgresql one as you won't be needing those.
  • open assemblyinfo.cs in the postgresql project and remove the line at the bottom which refers to the key to sign the assembly.
  • Open the PostgreSQLDBDriver project's properties -> Build events tab and clear the post build events.
  • Make sure the references are correct. It references assemblies from the designer, so simply add the assemblies from the llblgen pro installation folder.
  • Open PostgreSqlDBDriver.cs, at the top change driverVersion to something different, e.g. "3.5.10132016" so you'll see the designer is using your driver.
  • build the project in debug mode. You'll get a dll that's not signed.
  • go to <llblgen pro installation folder>\Drivers\PostgreSQL and first copy the dll from there to another folder, e.g. c:\temp\, so you can get back to the official one after this.
  • copy the debug built dll and pdb file from the postgresqldbdriver\bin\debug folder into the <llblgen pro installation folder>\Drivers\Postgresql, overwriting the one there.

Start the designer and load your project. It should load properly. Now go back to vs.net with the postgresql driver source loaded. Press Cntrl-Alt-P and attach the debugger to the llblgen pro designer. Place a breakpoint at: PostgreSQLDBDriver.cs, line 649

Now refresh your project with the postgresql server. You should hit the breakpoint in vs.net after you click 'Test connection' in the connection dialog. You can now see/check what the connection string looks like when it's used. It should look OK, even with the password embedded.

The connection string used, can be used to check whether it works with v2 npgsql by creating a normal ADO.NET console app and open an NpgsqlConnection object with the exact connection string.

To test whether it loads v2 or v3, add the following to the bottom of FillNETToDBTypeConversionsList() in PostgreSQLDBDriver.cs:

var connection = this.CreateConnection();

place a breakpoint on that line and re-try the refresh. You should hit that line and stepping over it will give you a real NpgsqlConnection object, you can then check which version is loaded.

Hopefully this gives enough info about what's going on!

Frans Bouma | Lead developer LLBLGen Pro
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 14-Oct-2016 12:15:24   

First thank you for such a detailed instructions - I could easily reproduce the steps. I can confirm that the v2.0.4.0 driver is loaded. Beside of it I found something more interesting using the source code of the driver and the value of "connectionString" variable, after it was initialized in the line 649 of PostgreSQLDBDriver.cs. Making long story short there is something wrong with the way System.Data.Common.DbConnectionStringBuilder parses its ConnectionString property value. Try the following code:

DbConnectionStringBuilder builder = new DbConnectionStringBuilder {
                ConnectionString =
                    "Database=my_db;Server=my_server;Port=5432;User Id=me;Password==abc;Encoding=ASCII;Protocol=3"
};
foreach( var key in builder.Keys )
                Console.WriteLine( key );

You will get:

database server port user id password=abc;encoding protocol

If the password doesn't start with the equal sign ("abc", not "=abc") we have:

database server port user id password encoding protocol

After the results of DbConnectionStringBuilder NpgsqlConnectionStringBuilder fails trying to set the value for its Password property and throws System.ArgumentException ("key=value argument incorrect in ConnectionString"). The exception doesn't allow LLBLGen to connect. As you can guess my real database password starts with equal sign and it triggered the unexpected problem.

Update: maybe I shouldn't blame DbConnectionStringBuilder - it seems that if we use it in ConstructConnectionString method of PostgreSqlDBDriver, instead of StringBuilder, it would produce connectionString with the quoted password.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 14-Oct-2016 17:02:34   

Hmm. so what should be done? 3.5 won't receive any patches, but obviously we haven't changed this code in later versions, as it's a typical pattern: keyword=<value> is used all over. I still think the npgsql ado.net provider should delimit on the ';' character first, then scan on the first '=' and it then should be able to deal with the password starting with '='.

Obvious workaround is changing your password to not start with a '=' but I guess you might not have the control over that disappointed I don't know how to escape the password so it gets parsed by npgsql.

Frans Bouma | Lead developer LLBLGen Pro
etk
User
Posts: 24
Joined: 27-Jul-2010
# Posted on: 18-Oct-2016 09:06:19   

I am aware that v3.5 is outdated and I consider v5.0 license. However I understand that the v5.0 drivers use StringBuilder and I can expect the same problem with my password. I suggest that maybe you could replace StringBuilder with DbConnectionStringBuilder. I have checked that using the class I can create valid connection string (there are quotation marks around the password) which is then properly parsed by npgsql.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Oct-2016 10:55:21   

That's indeed a great idea. We never considered this class (as it's just name-value pairs) but indeed it's better to use this class in edge cases like yours. We'll add this for v5.1

For 3.5, you can manually alter the postgresql driver source, as 3.5 won't be updated with patches so you won't run into problems if things get updated.

Frans Bouma | Lead developer LLBLGen Pro