ASP.NET application opening WAY too many SQL connections - asp.net

I have an issue on a codebit with an ASP.NET Webforms 4 application.
I am using SQL server 2008 R2, IIS 7, the website is running on Windows Server 2008 R2 in separate Application pool (integrated mode, .NET4, with support for 32bit assemblies).
The following code is posing problems:
Dim sqlCmd = New SqlClient.SqlCommand
With sqlCmd
Using sqlConnectionToUse As SqlClient.SqlConnection = GetActiveConnexion(pstrConnectString), _
vAdaptor As New SqlClient.SqlDataAdapter
.Connection = sqlConnectionToUse
.CommandText = pstrSQL 'function parameter
vAdaptor.SelectCommand = sqlCmd
'query1: SELECT somecolumn FROM table WHERE somecolumn '' ==> opens a new connection in SQL Server
'query2: SELECT someothercolumn FROM anothertable WHERE someothercolumn 23 ==> uses my WebSite process active connection
vAdaptor.Fill(vDataSet)
End Using
End With
UPDATE: the GetActiveConnexion() method simply does the following code in my case:
Return New SqlClient.SqlConnection("my connection string obtained from the web.config file")
When I run the query2, everything goes smoothly, the ASP.NET application uses the openned connection of the application pool and I get my results in the dataset.
However, whenever I run the query1, a NEW connection is openned in SQL server (I can see it show up in the SSMS's Activity Monitor) and this one remains openned. The problem is that If I run this query1 100 times, I reach the connection pool's limit and very bad things happens. I still gets the results in the dataset, can use them etc...
The new connection is created on the call of vAdaptator.Fill().
Any idea on what's wrong ?
Thanks a lot for your time.
(PS: sorry for the bad english).
Here is the code in C# for those who prefer:
object sqlCmd = new SqlClient.SqlCommand();
using (SqlClient.SqlConnection sqlConnectionToUse = GetActiveConnexion(pstrConnectString)) {
using (SqlClient.SqlDataAdapter vAdaptor = new SqlClient.SqlDataAdapter()) {
sqlCmd.Connection = sqlConnectionToUse;
sqlCmd.CommandText = pstrSQL; //function parameter
vAdaptor.SelectCommand = sqlCmd;
//query1: SELECT F10_ID FROM FIN_MONTANT_TT_F10 WHERE F10_ID_TT_F19 = '' ==> opens a new connection in SQL Server
//query2: SELECT A48_ID FROM ADH_EPARTICIPANT_ADMIN_A48 WHERE A48_ID=23 ==> uses my WebSite process active connection
vAdaptor.Fill(vDataSet);
}
}

Your SqlCommand instance should be wrapped in a using block as it's Disposable. It's probably the source of your problems.
using (SqlClient.SqlConnection sqlConnectionToUse = GetActiveConnexion(pstrConnectString))
{
using (SqlCommand sqlCmd = sqlConnectionToUse.CreateCommand())
{
using (SqlClient.SqlDataAdapter vAdaptor = new SqlClient.SqlDataAdapter())
{
...
}
}
}
Or VB
Using sqlConnectionToUse As SqlClient.SqlConnection = GetActiveConnexion(pstrConnectString)
Using sqlCmd As SqlCommand = sqlConnectionToUse.CreateCommand()
Using vAdaptor As New SqlClient.SqlDataAdapter()
...
End Using
End Using
End Using

Related

Passing datatable to SQL Server stored procedure not working

I have an ASP.NET application that passes a Datatable to a web service, then from the web service to a SQL Server stored procedure. When I publish the web application and web service to the server and run, it fails. When I run the application from the local host pointing to the web service on the server, it works fine. When I run the both the web application and web service from localhost, it works fine.
I did some troubleshooting and see that the following line is the problem but I am not sure how to solve:
cmdCommit.Parameters.AddWithValue(#SourceTable, dtSource);
When I comment the line above, everything works. When I replace the reference to the DataTable (dtSource) in the line above with a string datatype, it works.
Here is the entire web method, I am using this code within a try/catch block:
DataTable dtSource = ObjectToData(sourceTable);
dtSource.TableName = TableTypeObject;
using (SqlConnection cnn = new SqlConnection(_cnnSqlCapss))
{
SqlCommand cmdCommitChange = new SqlCommand("usp_Stored_Procedure", cnn);
cmdCommitChange.CommandType = CommandType.StoredProcedure;
cmdCommitChange.Parameters.AddWithValue("#Parm1", Value1);
cmdCommitChange.Parameters.AddWithValue("#Parm2", Value2);
cmdCommitChange.Parameters.AddWithValue("#Parm3", dtSource);
var returnParameter = cmdCommitChange .Parameters.Add("#ReturnVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
cnn.Open();
cmdCommitChange .ExecuteNonQuery();
var result = returnParameter.Value;
return (int)result;
}
The confusing part is that when I run the web application from the localhost and reference the web service on the server, it works. I don't understand why it fails when I run the web application from the server.
When I comment the line that reference the DataTable everything works.
I have tried the following and still no success:
SqlParameter tvpParam cmdCommit.Parameters.AddWithValue "#SourceTable", dtSource);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.SourceTableType";
Also, The web method is not throwing an exception.
Assumed you're already doing these:
Defining table type in User-Defined Table Types in your database (often known as TVP, see reference section below);
Adding parameter to pass DataTable to stored procedure (e.g. #SourceTable).
Then, you can use SqlDbType.Structured to pass DataTable contents as stored procedure parameter like this:
cmdCommitChange.Parameters.Add("#SourceTable", SqlDbType.Structured).Value = dtSource;
Alternative with AddWithValue:
cmdCommitChange.Parameters.AddWithValue("#SourceTable", dtSource).SqlDbType = SqlDbType.Structured;
Example usage in SqlConnection block:
using (SqlConnection cnn = new SqlConnection(_cnnSqlCapss))
{
SqlCommand cmdCommitChange = new SqlCommand("usp_Stored_Procedure", cnn);
cmdCommitChange.CommandType = CommandType.StoredProcedure;
cmdCommitChange.Parameters.AddWithValue("#Parm1", Value1);
cmdCommitChange.Parameters.AddWithValue("#Parm2", Value2);
cmdCommitChange.Parameters.AddWithValue("#Parm3", Value3);
// add this line
cmdCommitChange.Parameters.Add("#SourceTable", SqlDbType.Structured).Value = dtSource;
cmdCommitChange.Parameters.Add("#ReturnVal", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
cnn.Open();
cmdCommitChange.ExecuteNonQuery();
var result = (int)returnParameter.Value;
return result;
}
Reference:
Table-Valued Parameters (MS Docs)
I found the problem. I am passing a text value that is too large for a column on my datatable.
The web service was indeed throwing an exception but there was some code in my application's routine which was preventing me from seeing it.

Asp.net "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."

I am facing one problem in asp.net Application with sql server database.
I am getting Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
In my code stored procedure is taking around 43 seconds and after 30 seconds
I am getting this error. For Solving this I have analyzed many sites and found these solutions:
I need to set Connection Timeout=300 in connectionString in web.config file.
This point I have done, but still I get the same error.
I also need to set commandTimeout through code.
My problem : I am not able to modify the default commandTimeout
Because I am using DataTier_Using_SQLClient to connect to database.
This does not contain the commandTimeout property .
Actually default command timeout is 30 seconds only.
Assuming you are using an Adapter
DataSet dsData = new DataSet();
SqlConnection conn = new SqlConnection(GetConnection());
SqlDataAdapter adapter = new SqlDataAdapter(strQuery, conn);
adapter.SelectCommand.CommandTimeout = 120;
Thank you very much Tim B James and January Mmako
Actually I was solving one issue related to one application.
DataTier_Using_SQLClient is one class in my application to connect with Database.
Then forget this class.
I have solved this issue by creating connection using SqlConnection.
See the code below. Using this code you can solved the Time Expired Error
and can call retrieve stored procedure having one parameter that need to pass:
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
use the below code where you want
string connetionString = null;
SqlConnection connection ;
SqlDataAdapter adapter ;
SqlCommand command = new SqlCommand();
SqlParameter param ;
DataSet ds = new DataSet();
//You can specify this connectionString in web.config or here
connetionString = "Data Source=servername;
Initial Catalog=PUBS;User ID=sa;
Password=yourpassword;
Connection Timeout=300";
connection = new SqlConnection(connetionString);
connection.Open();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "sp_Retrieve_ProcedureName";
param = new SqlParameter("#paramName", ParamValue);
param.Direction = ParameterDirection.Input;
param.DbType = DbType.Int32;
command.Parameters.Add(param);
adapter = new SqlDataAdapter(command);
adapter.SelectCommand.CommandTimeout = 120;
adapter.Fill(ds);
you can use this ds (DataSet) object where ever you want.

How to set database with AdomdConnection

When I execute this code:
AdomdConnection con = new AdomdConnection("Data Source=MyServer;User ID=MyDomain\\MyUserName;Password=MyPassword");
con.Open();
con.ChangeDatabase("Analysis Services Project1");
I get this exception:
Either the user, MyDomain\MyUserName$, does not have access to the
Analysis Services Project1 database, or the database does not exist.
The database name comes from looking at the server using Microsoft SQL Server Management Studio. If I bring up the properties on the server and go to the security section, my account is listed as a Server administrator. While in management studio, I can see data sources, cubes and execute mdx queries fine.
Why can't do I get this exception in code?
whihc line causes the error?
I imagine you have to infor the catalog on your connection string. Try addind
Catalog=Analysis Services Project1
to your con string.
Also, Analysis Services Project1 seems to be the projects name? Are you sure this is the database name as well?
First
added the reference for Microsoft.AnalysisServices.AdomdClient.dll
strCon = "Data Source=DBserverServerName;Integrated Security=SSPI;Initial Catalog=DBName;";
AdomdConnection con = new AdomdConnection("connectionstring"); // connect DB con.Open(); AdomdCommand cmd = new AdomdCommand("MDX query", con); //query
AdomdDataReader reader = cmd.ExecuteReader(); //Execute query
while (reader.Read()) // read
{
Data dt = new Data(); // custom class
dt.Gender = reader[0].ToString();
dt.Eid = reader[1].ToString();
dt.salary = reader[2].ToString();
data.Add(dt);
}

Enterprise Library 5.0 Connection Pool Timeout

I have an old web application written in ASP.Net 2.0 Web Forms. I use the Data Access Block in Enterprise Library and have recently updated to version 5.0. The application is tiered, ie, UI layer, Service Layer, Data Layer. It also uses SQL Server 2008 for the data storage.
I have recently noticed that the following error is appearing when I run the application and browse to particular pages.
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.
This tends to happen on pages that do a lot of separate reads from the database, maybe up to as many as 20 on one page.
Below shows snippets of my Data Access Class.
Public Class DataAccess
' create a private instance of the database factory
Private db As Database = DatabaseFactory.CreateDatabase()
Public Function ExecuteNonQuery(ByVal params() As SqlParameter, ByVal strSproc As String) As Integer
Dim intReturnValue As Integer = 0
Dim i As Integer
Dim cmd As DbCommand
cmd = db.GetStoredProcCommand(strSproc)
cmd.CommandTimeout = 120
For i = 0 To params.Length - 1
db.AddInParameter(cmd, params(i).ParameterName.ToString, params(i).DbType, params(i).Value)
Next
db.AddParameter(cmd, "return_value", DbType.Int32, ParameterDirection.ReturnValue, "", DataRowVersion.Default, 0)
db.ExecuteNonQuery(cmd)
intReturnValue = Int32.Parse(db.GetParameterValue(cmd, "#return_value"))
Return intReturnValue
End Function
Public Function ExecuteDataReader(ByVal params() As SqlParameter, ByVal SProc As String) As SqlDataReader
Dim i As Integer
Dim dr As SqlDataReader = Nothing
Dim cmd As DbCommand
cmd = db.GetStoredProcCommand(SProc)
cmd.CommandTimeout = 120
For i = 0 To params.Length - 1
db.AddInParameter(cmd, params(i).ParameterName.ToString, params(i).DbType, params(i).Value)
Next
dr = TryCast(DirectCast(db.ExecuteReader(cmd), RefCountingDataReader).InnerReader, SqlDataReader)
Return dr
End Function
Throughout my code, once I have finished with an SqlDataReader I always do something like this
If Not (drSource Is Nothing) Then
drSource.Close()
End If
Is there anything you folk can see that I am missing? Does it look like my code could be leaking connections or not closing properly?
I always thought the Garbage collector got rid of any open connections.
Any feedback or help would be greatly appreciated.
Thanks.
Your code is closing the data reader, but not the data connection associated with it.
Since your data reader is a SqlDataReader, it has a Connection property. You should be able to use that to close and dispose of the connection.

how do i connect to oracle with the info i have?

i have the info below from the oracle DBA and want to connect to oracle from a .net application. i just got done installing the oracle tools/ drivers for windows/ .net and now want to get a console app to connect tot he oracle DB and extract data from oracle into SQL server.
another solution would be to have SQL server pull from oracle all the records in the bugs table. i have no clue what the oracle connection string is and have tried to create a system DSN but failed at that prior to turning to the SO gurus...
ORACLE SQL user name is ‘USER_dev’,
password is ‘welcome’.
Connection string is
‘jdbc:mercury:oracle://qct-ds2-p.apps.com:1139;sid=QCTRP1’
i got lucky and found a simple solution that is all in .net and requires nothing more than this syntax by way of a connection string. all the .ora stuff is presented in the connection string and works well.
static void getData()
{
string connectionString = GetConnectionString();
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
//Console.WriteLine("State: {0}", connection.State);
//Console.WriteLine("ConnectionString: {0}", connection.ConnectionString);
OracleCommand command = connection.CreateCommand();
string sql = "SELECT * FROM BUG";
//string sql = "SELECT table_name FROM user_tables";
command.CommandText = sql;
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//string myField = (string)reader["Project"];
string myField = (string)reader[0];
Console.WriteLine(myField);
}
}
}
static private string GetConnectionString()
{
return "User Id=USER_dev;Password=welcome;Data Source=(DESCRIPTION=" +
"(ADDRESS=(PROTOCOL=TCP)(HOST=111.123.479.24)(PORT=1139))" +
"(CONNECT_DATA=(SID=QCTRP1)));";
}
go into your ORACLE_HOME\network\admin directory. Create a file called tnsnames.ora if it is not there already. Add this into it:
QCTRP1.WORLD =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = qct-ds2-p.apps.com)(PORT = 1139))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = QCTRP1)
)
)
I'm making some assumptions here...
does qct-ds2-p.apps.com resolve?
looks like the DBA set it up the listener on port 1139... default is normally 1521 so you'll need to confirm.
You can then set up a connection string as follows:
Connection conn = DriverManager.getConnection
("jdbc:oracle:oci8:#QCTRP1.WORLD", "dev", "welcome");
now that you have the tnsnames created from #erbsock, you will need to get the .net side of
things working. Oracle has several tutorials available to help you in this matter.
When you install the Oracle ODP (in the link you will see samples as well as the downloads) drivers you will get a directory created in the
%oracle_home%\odp.net\samples\4\DataSet\DSPopulate\src
(this appears to be the same example as located # http://www.oracle.com/technology/sample_code/tech/windows/odpnet/DSPopulate/ViewProducts.cs.html)
as an initial test I would recommend just changing around the id/passwrd/sql/etc and trying it out.
it is not that fundamentally different than using System.Data; but there are a few gotchas and remember that each computer will need to have ODP/Oracle client installed to have them work with the ora connection.
if you have any problems post the exact error msg that is displayed as well as a snippet of your .net code that establishes the connection, does the query, and where it is breaking

Resources