Timeout Connecting to SQL Server 2016 - c#

We recently upgraded to SQL Server 2016 from SQL Server 2014 and since doing so a repository is getting a EntityCommandExecutionException with the InnerException of {"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."} after ~15 seconds after executing the repo.
I can manually increase the timeout length in the model to fix this, but it seems rather odd since this repo was working fine prior to the SQL Server upgrade. The underlying database/model, size of the data we're retrieving, and server settings are also unchanged. Is there something related to using EF 6 & .NET 4.6.1 with SQL Server 2016 that I'm not taking into account?
Below is the code with a hardcoded connection string to see if there's anything in there that needs to be modified for SQL Server 2016 specifically.
Model Constructor (w/ timeout amount increased as a workaround)
public OperationsModel(string connectionString, bool lazyLoading = false)
: base(connectionString)
{
Database.CommandTimeout = 500;
Configuration.LazyLoadingEnabled = lazyLoading;
Configuration.ProxyCreationEnabled = lazyLoading;
}
Method
public void Example()
{
//X'ed out the server and database, but those are correct
using (var uow = new ModelManager(new OperationsModel("data source=XXXXX;initial catalog=XXXXX;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework\" providerName=System.Data.SqlClient")))
using (var repo = new MyRepository(uow))
{
var test = repo.GetAll().ToList(); //Exception gets thrown here
}
}

Related

How to make SqlConnection.RetrieveStatistics work?

I can't make SqlConnection.RetrieveStatistics work, it always return a hashtable of 18 elements that are all zeros.
What I want to do : In my test environnent, I want to add a header for each httpresponse with the number of sql commands that were executed during the request processing.
My app is only (Rest) webservices, I have one sql connection par request ( One NHibernate session per request ).
After the request is processed, I do :
var connection = statelessSession.NHSession.Connection as ReliableSqlDbConnection;
if (connection != null)
queries += Convert.ToInt32(connection.ReliableConnection.Current.RetrieveStatistics()["Prepares"]);
The number is always 0, and when I break on this line, I see that all numbers are zeros.
After the session is opened, I do :
var ret = module.OpenSession();
var connection = (ret.Connection as ReliableSqlDbConnection);
if(connection != null)
{
connection.ReliableConnection.Current.StatisticsEnabled =true;
ret.CreateSQLQuery("SET STATISTICS IO ON; SET STATISTICS TIME ON;").ExecuteUpdate();
connection.ReliableConnection.Current.ResetStatistics();
}
return ret;
I use https://github.com/MRCollective/NHibernate.SqlAzure because in production I'm using sql azure, but in local I have an instance of Sql Server 2014 Developer Edition.
For my database, I have :
Auto create statistics true
Auto update statistics true
Did I miss something ?
The cause of this was that NHibernate opens a new connection for each request, this is why I was loosing the statistics each time.

C# MongoDB.Driver : How to see if server is connected. GetServer Replacement

GetServer is gone for good. How do i check if the server is connected or even exists?
Example code:
// This server exists
var exists = new MongoClient("mongodb://192.168.2.109:27017");
// This server does not exist
var doesNotExist = new MongoClient("mongodb://194.168.200.129:27017");
// Both states return "Discennected"
var connStateExisting = exists.Cluster.Description.State;
var connStateNotExisting = doesNotExist.Cluster.Description.State;
// GetDatabase("name") works for both without errors.
How can i check if a server can be connected?
The Cluster.Description.State does not update immediately. When i checked, it was updated after roughly 100+ milliseconds. The driver contains a connection pool and it seems to do quite a lot asynchronous.
However, the Cluster-property has a "DescriptionChanged"-event that is fired once the connection is done.
If someone else has any knowledge about connections and timeouts, please share it.

SqlConnection pooling doesn't seem to work

I'm trying to optimize my code performance accessing SQL Server 2014 database and noticed that connection pooling doesn't seem to work as advertised by ADO.NET. By default it's supposed to be enabled and working out of the box (as long as same connection string is used). My experiments are showing however that opening/closing connection on SqlConnection does in fact cause Audit Login / Logout to be raised.
As per https://msdn.microsoft.com/en-us/library/vstudio/8xx3tyca(v=vs.100).aspx this should not be the case:
Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool. This is because the connection is not actually closed when it is returned to the connection pool.
My simple test was to create a console app, similar to the following:
var conn = new SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=icedb;");
for (int i = 0; i < 3; i++)
{
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText = "select 1";
cmd.ExecuteScalar();
conn.Close();
}
Running this code yeilds results captured by Sql Profiler similar to the following. Observer the multiople login/logout events which should have not been captured if pooling was working as advertised. I've been able to reproduce this on multiple machines (Windows 8/10, .NET 4.5, Sql Server 2014 Developer Edition).
Main question: How do I get connection pooling to work.
If sp_reset_connection is issued then connection pooling is enabled. See What does sp_reset_connection do?
To see if an Audit Login is pooled or non-pooled in the Profiler, you need to add EventSubClass column to the Trace and check the Audit Login and Audit Logout events. The new column will show either "1 - Nonpooled" or "2 - Pooled".
In your example only the first connection has "1 - Nonpooled", the next 2 Audit Logins have EventSubClass = "2 - Pooled".

Right code to retrieve data from sql server database

I have some problems in database connection and wonder if I have something wrong in my code. Please review. This question is related: Switch between databases, use two databases simultaneously question.
cs="Data Source=mywebsite.com;Initial Catalog=database;User Id=root;Password=toor;Connect Timeout=10;Pooling='true';"
using (SqlConnection cnn = new SqlConnection(WebConfigurationManager.ConnectionStrings["cs"].ConnectionString))
{
using (SqlCommand cmmnd = new SqlCommand("", cnn))
{
try
{
cnn.Open();
#region Header & Description
cmmnd.Parameters.Add("#CatID", SqlDbType.Int).Value = catId;
cmmnd.CommandText = "SELECT UpperID, Title, Description FROM Categories WHERE CatID=#CatID;";
string mainCat = String.Empty, rootCat = String.Empty;
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
if (rdr.Read())
{
mainCat = rdr["Title"].ToString();
upperId = Convert.ToInt32(rdr["UpperID"]);
description = rdr["Title"];
}
else { Response.Redirect("/", false); }
}
if (upperId > 0) //If upper category exists add its name
{
cmmnd.Parameters["#CatID"].Value = upperId;
cmmnd.CommandText = "SELECT Title FROM Categories WHERE CatID=#CatID;";
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
if (rdr.Read())
{
rootCat = "<a href='x.aspx'>" + rdr["Title"] + "</a> ยป ";
}
}
}
#endregion
#region Sub-Categories
if (upperId == 0) //show only at root categories
{
cmmnd.Parameters["#CatID"].Value = catId;
cmmnd.CommandText = "SELECT Count(CatID) FROM Categories WHERE UpperID=#CatID;";
if (Convert.ToInt32(cmmnd.ExecuteScalar()) > 0)
{
cmmnd.CommandText = "SELECT CatID, Title FROM Categories WHERE UpperID=#CatID ORDER BY Title;";
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
while (rdr.Read())
{
subcat.InnerHtml += "<a href='x.aspx'>" + rdr["Title"].ToString().ToLower() + "</a>\n";
description += rdr["Title"] + ", ";
}
}
}
}
#endregion
}
catch (Exception ex) { HasanG.LogException(ex, Request.RawUrl, HttpContext.Current); Response.Redirect("/", false); }
finally { cnn.Close(); }
}
}
The random errors I'm receiving are:
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Cannot open database "db" requested by the login. The login failed. Login failed for user 'root'.
There's no real issues here.
You don't need the extraneous finally { cnn.close(); } as the using clause will take care of that for you. However changing it will have exactly zero impact.
Another thing is that I would put the try .. catch outside of the using clause with a redirect. But, again, I don't think that would affect the dispose from being called.
It's interesting that you would get connection pool errors (timeout expired) if you are always properly disposing of your connections, as you've shown.
Which leaves us with only one real solution: switch hosting providers. They have either overloaded their DB server to the point of unusability or some hardware element in their network setup (nic, switch, router, etc) is bad and dropping packets.
There are couple of inconsistencies which need to fixed:
description = rdr["Title"]; no proper casting defined.
Same command object is used for each sql statement and even you are not clearing parameters, it would be ideal if a separate command should be used for each sql statement.
Too many redirections as well, it is best to handle redirection at the end of method.
Check the database server health as well, it looks like database server is not responsive enough.
Hope it will help.
If you're connecting remotely to a database provider, you need to look at several possibilities like your own network configuration, firewall setup, etc.
Use a packet sniffer to figure out if lost packets are the issue.
Connection pooling is setup on your local machine, the server making the connections. If the database provider only allows for 5 connections and your connection pool is setup for 50 connections, well... you can do the math. It looks like you're closing the connections properly, so no issues there.
True... one error on "description = rdr["Title"];", should that be "description = rdr["Description"].ToString()"?
No need to put a using statement around the SqlCommand object and since you're using ad-hoc queries, just use string.Format("sql test {0}", param). This way, you can reuse the SqlCommand object without having to clear the parameters.
The biggest issue I see here is that you've mixed the presentation layer with the business layer with the datasource layer. Dump the try...catch and allow the business layer to handle logging stuff. Return an object to the presentation layer and allow it to perform the redirects. Keep the datasource layer very simple... get the data and return an entity. The business layer can handle any business logic on the entity itself.
SQL Server not found could be your fault or the providers... if the provider is at fault often, change providers.
Are you sure that the DB is configured to grant remote access using TCP?

SQL Server Replication Error

I have a SQL Server 2005 box set up for merge replication to SQL Server CE 3.0. The publication, publisher, distributor and IIS have all been set up.
In my application, I attempt to sync the databases using the following code:
//TODO: Change for production
//***************************
string localDBPath = #"C:\Documents and Settings\Robert\Desktop\MyDB.sdf";
//***************************
SqlCeReplication replicator = new SqlCeReplication();
replicator.InternetUrl = "http://myWebServer/sqlcesa30.dll";
replicator.Publisher = "mySqlServer";
replicator.PublisherDatabase = "myDatabase";
replicator.PublisherSecurityMode = SecurityType.NTAuthentication;
replicator.Publication = "myPublication";
replicator.Subscriber = Dns.GetHostName();
replicator.SubscriberConnectionString = #"Data Source=" + localDBPath;
try
{
// Check if the database file already exists
if (!System.IO.File.Exists(localDBPath))
{
// Add a new subscription and create the local database file
replicator.AddSubscription(AddOption.CreateDatabase);
}
// Transfer the initial snapshot of data if this is the first time this is called.
// Subsequent calls will transfer only the changes to the data.
replicator.Synchronize();
}
catch (SqlCeException ex)
{
// Display any errors in message box
MessageBox.Show(ex.Message);
}
finally
{
// Dispose of the SqlCeReplication object, but don't drop the subscription
replicator.Dispose();
}
Unfortunately, this code fails at the "replicator.Synchronize" line with the following error message:
Failure to connect to SQL Server with provided connection information. SQL Server does not exist, access is denied because the IIS user is not a valid user on the SQL Server, or the password is incorrect.
This error message is not very clear to me and I am running out of places to look for the cause of this. Any ideas?
Make sure the agent account is the same user and password on all boxes.
Make sure you are calling the right instances.
Make sure agent is started on all machines involved.
Check the sql event logs on all servers and see which is giving the error, this may also narrow the issue down.
You can also check this to make sure you have setup correctly:
http://msdn.microsoft.com/en-us/library/aa454892.aspx
Same issue here he had to add the instance name correctly:
http://bytes.com/topic/sql-server/answers/611761-merge-replication-error-failure-connect-sql-server-provided-connection
Check these out too:
http://support.microsoft.com/kb/314783
http://support.microsoft.com/kb/319723
http://msdn2.microsoft.com/en-us/library/ms172357.aspx
again make sure you instances are correct:
repl.Publisher = "macnine-name\instance-name"
You can also take a look through this blog:
http://blogs.msdn.com/sql_protocols/archive/2005/09/28/474698.aspx
the message comes from your IIS replication plug-in: //myWebServer/sqlcesa30.dll. When it tries to connect to the publisher, it cannot find it. The publisher is named 'mySqlServer', but apparently it cannot be reached by myWebServer. This can be a name issue (a typo), a firewall issue (SQL port blocked), an IPSEC issue, a configuration issue (SQL is not listenning for remote connections) and so on. Follow normal SQL Server connectivity troubleshooting steps between myWeServer and mySqlServer.

Categories

Resources