Slow first NpgsqlConnection in YugabyteDB YSQL - npgsql

[Question posted by a user on YugabyteDB Community Slack]
It seems that connecting to a cluster is “slow” the first time through NpgsqlConnection.
Is this normal PostgreSQL behaviour or is this related to YugabyteDB?
We are using the latest 6.0.0-preview7 nuget to use the multi host connecting string for load balancing.

According to Allow extensibility in type loading and database capabilities · Issue #1486 · npgsql/npgsql, extra calls are made to system tables to map types when the first connection is created. In order to avoid the initial call, you can set connStringBuilder.ServerCompatibilityMode = ServerCompatibilityMode.NoTypeLoading; on the connection string. When setting this property the first call is not made and the connection will be faster.

Related

Universal Windows Platform (UWP) and SQL Server

I've hit a wall when it comes to how the Universal Windows Platform connects/manages/interacts with a local SQL Server database. My current project (WPF using .NET Framework 4.8) that I'm interested in porting over to UWP uses EntityFramework 6 with ADO.NET models and it works like a charm. No issues at all. UWP on the other hand, well I'll just say that I have absolutely no idea what's going on when it comes to connecting to a local instance of SQL Server. I've gone through about 3-4 different guides/templates and none have worked. I really want to use UWP and take advantage of all the new features coming for Windows 10 v2004, but it doesn't look like this will happen.
As I currently understand the process, I need to essentially create two separate projects within the same solution. One is the UWP main program and the other would be a .NET Core class library that targets the .NET Standard 2.0 platform. I also have read that EntityFramework 6 is not supported on .NET Core or UWP, so the only way is by using EntityFrameworkCore (more specifically NuGet package Microsoft.EntityFrameworkCore.SqlServer). So I installed it on the .NET Core class library and then set a reference from the UWP app to the class library. Because the local SQL Server is already up and running, I'm not doing what is called the 'code first' approach to the creation of all the models/DbContext.cs files. Based on what I've read, the ONLY way to import a currently existing SQL Server into the data model is by use of the Scaffold-DbContext command with a standard connection string through the package manager. Surprisingly, this worked on the first attempt and the models and DbContext were all created without any issues.
This is about as far as I seem to be able to get as everything after does nothing but throw exceptions. If I try to pass any C# code using the DbContext to retrieve any data from the database, I get about 10-15 exceptions that essentially say the program can't find or connect to the database. I have manually edited the connection string in every way imaginable, but nothing seems to work. I also tried to manually set up a new connection using Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient.SqlConnectionStringBuilder and System.Data.SqlClient.SqlConnection but they all fail with the same exceptions.
Sorry for the long post but at this point, I really don't know what's going on and would really appreciate any feedback you all could offer.
Update 1
So, I went back through my currently working app on .NET Framework and looked for the connection string in the App.config file to see what the regular EntityFramework is using and it's completely different than anything I've used before. My guess is that it's generating a completely custom connection string that includes references to all sorts of files and a property called 'ProviderName'. Will try cutting and pasting this string into UWP to see if it'll work.
Update 2
I think I'm missing something fundamental on this. I can generate the scaffold with a connection string without any issues, but if I attempt to open a connection at runtime using the same connection string, I'm getting errors.
Finally was able to get a connection at runtime after months of trial and error. Without getting into too much detail, here's what worked for me (assuming EFCore has already generated a DbContext file):
Enable Enterprise Authentication.
Enable TCP/IP connections to the SQL Server instance.
In Visual Studio's server explorer, click Add Connection. If you already have a connection saved for the database, right click the server and click Modify Connection
In the connection properties window, click the Advanced button. Make a note of all of the listed parameters and their values and save it.
Open the data context file that isn't able to connect and add a using statement for Microsoft.Data.SqlClient. Now locate the OnConfiguring method. Use a SqlConnectionStringBuilder and configure all of the parameters from the advanced connection properties that were saved earlier.
And that should work. If there are still errors, I would double check the parameters to make sure they were all entered correctly.
Hope this post will help out anyone else dealing with this issue.

DBCP Connection Pool loginTimeout

According to the DBCP Document, BasicDataSource does not support setLoginTimeout(). My question is then how do I set a LoginTimeout for the creation of Connection objects? I know I can set maxWait on the pool, but my understanding is that that'll only be used for when the pool is exhausted and you're waiting for an existing connection to free up. It will not save me from the situation where a new connection needs to be created, but the connection/login into the DB hangs.
Any help is appreciated. Thanks.
Well there is always an option to add correct parameter to the URL. Depending on which DB you are using you can add one of the parameters in JDBC url.
Here is the link that confirms that BasicDataSource does not support loginTimeout
And at the bottom of this blog There is a table which lists URL parameters for connection timeouts.
#Sap is right, you might use the JDBC url in order to add connection properties, for example:
basicDataSource.setUrl("jdbc:postgresql://192.168.0.100:5432/postgres?connectTimeout=TIME_IN_SECONDS");
Where TIME_IN_SECONDS can be any intenger value.
Besides, we can use BasicDataSource#setConnectionProperties. As the parameter says:
The connection properties that will be sent to our JDBC driver when establishing new connections.
Format of the string must be [propertyName=property;]*
NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here.
So, it might be something like (and following the previous example):
basicDataSource.setUrl("jdbc:postgresql://192.168.0.100:5432/postgres");
basicDataSource.setConnectionProperties("connectTimeout=TIME_IN_SECONDS");
P.S:
You can add more properties using ; at the end of the property.

Clearing Access Cache

I am developing a system in Access talking to a Sql Server backend. I can connect with two separate accounts A and B so that I can control permissions. In particular I have a view which is accessed via a pass through query which is denied to A but allowed by B.
Normally selection of A or B as the login is related to which Access Security Group the user belongs in, but I have set it up so that people in the Admins group (ie me) read the login from an internal access table. I have also created a form (and associated code) that allows an Admin to change this value.
This all works great and does its job perfectly - provided I start up Access from scratch.
It detects I am admin, reads the last value I set in the internal table, connects to the server with the correct login string (I loop deleting and re-creating all the tabledefs using this new connection string) and then displays my first form. I navigate to a button that runs the pass through query. When I click that button it recreates the pass through query, by deleting one with the same name and recreating it with the correct connection string (A or B login) before then running it to output results. If I am A, then it fails with a permission error (which I display and inform the user about), if I am B it works and I get the results.
I have added a system to attempt to change this on the fly for testing purposes. Having changed who Admin should login as (by writing to an internal table), it recalls the startup code, which loops through deleting and re-creating tabledefs and then puts me back at the intial form.
HOWEVER - If I now navigate to the button that runs my permission controlled query, it still deletes and re-creates the query def from scratch, but when I run it, it seems to run in the context of the SQL Server Login it set when I first started access, and not the new SQL Server Login I have just re-created everything with. So the query will run when it shouldn't (of visa versa).
If I exit Access and try again - it starts working properly again.
The only conclusion I can draw from this is that somewhere inside of Access it is caching the ODBC connection string - and instead of using the new one is using the old.
So my question is - is my conclusion correct, and if so how can I tell Access to clear its cache.
I am developing in Access 2010 - for a system that will ultimately be running in an Access 2000 environment - so the file format is an .mdb in the Access 2000 format.
I came to this topic because I had the same question: "How to clear the cache in Access 2010?"
In my case, the problem was that my application somehow "remembered" the entire path to my linked photos, even though I referenced only the file name. One of the links above lead me to search under "File > Current Database > Caching Web Service and SharePoint tables." The option to "Use the cache format that is compatible with MS Access 2010" was already checked, but I enabled the check box for "Clear Cache on Close" and closed the database.
Voila! All previously cached values, including the values for my linked photos, were cleared out. It doesn't appear that this setting affected my ODBC DNS-less connections, but I haven't confirmed this.
**TO CLEAR CACHING, go to File-->**OPTIONS-->Current Database, and scroll down to Caching Web Service and SharePoint tables.****
Can this page about ODBC linked access password reset be what you're looking for ?
As far as I know, there is no way to clear this cache. If you execute a query and supply a different UID/Password for that query, then the permissions you obtained from that act will remain in effect until such time you close down Access.
Thus if you execute another query and supply a "differnt" UID/password, and then later own execute another query with “lower” permissions, the other cached UID/password will be used. So you can (and will) have multiple UID/passwords cached at this point in time - you have no control over which one is used.
The only way around this would be to adopt a separate ADO query – this to my knowledge does not cache the credentials like when using DAO queries.

Site update, testing was fine, after deployment, again fine, once user load increases, FAIL?

We are using ASP.NET MVC with LINQ to SQL. We added some features and tested them all to perfection on our QA box. We are using Windows Server 2003 and SQL Server 2005. So when we pushed out changes to the Live web server we also used Red Gate SQL Compare to push new database changes to the LIVE database. We tested again between the few of us, no problems. Time for bed.
The morning comes and users are starting to hit the app, and BOOM. We have no idea why this would happen as we have not been doing any new types of code things that we were not doing before. However we did notice that during the SQL Compare sync the names of all the foreign keys were different between the two databases, not the IDs in the tables, FK_AssetAsset_A0EB67 to FK_AssetAsset_B67EF8 (for example, don't remember the exact number of trailing mixed characters during the SQL Compare), we are not sure why but that is another variable in this problem.
Strangely once this was all pushed out we could then replicate the errors on QA, but not before everything was pushed to LIVE.
QA and LIVE databases are on the same SQL Server, but the apps are on different instances of Windows Server 2003.
Errors generated:
Index was outside the bounds of the array.
Invalid attempt to call FieldCount when reader is closed.
Server failed to resume the transaction.
There is already an open DataReader associated with this Command which must be closed first.
A transport-level error has occurred when sending the request to the server.
A transport-level error has occurred when receiving results from the server.
Invalid attempt to call Read when reader is closed.
Invalid attempt to call MetaData when reader is closed.
Count must be positive and count must refer to a location within the string/array/collection. Parameter name: count
ExecuteReader requires an open and available Connection. The connection's current state is connecting.
Any one have any idea what the heck could have happened?
EDIT: Since we were able to replicate the errors all of a sudden on QA, it might not be a user load issue... Needless to say we all feel really screwed here.
Concurrency always brings bugs out of the woodwork. I'd recommend you check for objects that could be shared among requests (such as static members and singletons) and refactor your code so that as little as possible is shared.
As far as specifics go, for the error "There is already an open DataReader associated with this Command which must be closed first," you may want to try adding MultipleActiveResultSets=True to your connection strings.
It sounds like you're crossing the streams a bit and trying to share DataContexts across requests. My suggestion would be to wire in a dependancy injection framework that creates a new instance of the dependancy for each request.
I use Castle's IoC and wire it into the controller factory so that when it sees a dependancy on a repository it creates a new instance of that repository for each request. If you go this route let me know and I can shoot you a few more resources.

Why does an Entity Framework Connection require a metadata property?

I switched my DAL from using LINQ over to Entity Framework. Because my application connects to different databases depending on the current user, I need to dynamically create the DataContext at run time and pass in the appropriate connection string. However, when I tried to programatically create an Entity Framework connection using my old connection string, the connection failed. It complained that it didn't recognize the key in the connection string, "server" to be exact.
I found out that I needed to do this in order to get the Entity Framework connection to work:
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = "System.Data.SqlClient";
entityBuilder.ProviderConnectionString = clientConnectionString;
entityBuilder.Metadata = "res://*/xxxxxxxxxx.csdl...";
Entities entities = new Entities(entityBuilder.ToString());
Why is this?
What is the Metadata property for?
Is it going to be a problem that its always the same for multiple different connections?
What should it be?
Is there any way around this?
Thanks in advance!
Update 1:
Thanks for the update Randolpho, but...
The whole reason I'm having this issue, is that I can't store the connection strings in a configuration file. The connection string is dynamically determined at runtime by which user is connecting.
Here is my exact scenario:
If user A is connecting, the app pulls data from database A. If user B is connecting, the app pulls data from database B.
The connection strings are stored in a main database, and the number is potentially limitless. Every time I add a user, I don't want to have to go into the web.config, not to mention the fact that it would eventually get HUGE!
Expanding on Randolpho's answer:
The metadata property specifically points to the location of the .SSDL (Storage Model,) .CSDL (Conceptual Model,) and .MSL (Mapping Model) files. These three files essentially are the Entity Data Model. The "res://" URI-style qualifier indicates that the files are embedded as resources in the compiled EDM assembly.
You will find these links very informative:
http://msdn.microsoft.com/en-us/library/system.data.entityclient.entityconnection.connectionstring.aspx
http://weblogs.asp.net/pgielens/archive/2006/08/21/ADO.NET-Entity-Framework-Metadata.aspx
Bottom line? Entity Framework needs the metadata to build your entity mappings.
Additionally, you should consider moving your connection information out to your configuration file rather than build it in code. The first link will show you how to do that.

Resources