I am trying to run a non query using a Oracle connection in ASP C# with CLR 4.5. Here is my code:
string connectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString1"].ConnectionString;
OracleConnection conn = new OracleConnection(connectionString);
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "update SALES_ADVENTUREWORKS2012.SALESORDERDETAIL set UNITPRICEDISCOUNT=0 where ROWGUID='4A399178-C0A0-447E-9973-6AB903B4AECD'";
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = QUERY_TIMEOUT;
int row_affected = cmd.ExecuteNonQuery();
HttpContext.Current.Response.Write("Rows affected:" + row_affected + "<br/>");
conn.Close();
when I run the query in oracle development tool, it works fine.
when I use the asp code above, it freezes when performing the query. It freezes forever even though I used a 5 second timeout.
I've tried using the managed and unmanaged oracle libraries; both behave the same.
Note that using the fill or scalar query work perfectly fine so there is nothing wrong with my connection string. Also the fact that oracle development can perform this update query proves that this is not a permission problem.
Any ideas?
Most likely your query is waiting to get access to the record. You probably have modified that row in "oracle development tool" and have not committed or rolled back that transaction.
Just commit/rollback in your tool or close open session.
You can check for open transactions in v$transaction view.
More on automatic locks in Oracle:
http://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm
Are you certain you are using the 4.5 library? The 3.5 documentation states that the CommandTimeout property has no effect.
The 4.5 documentation suggests it should work, but the Remarks section doesn't mention the change, which warrants suspicion.
Otherwise, the code you posted doesn't seem to show where you actually set the value of QUERY_TIMEOUT to 5 seconds. If QUERY_TIMEOUT has a value of zero, then any other provider (SQLCommand, for example) would wait indefinitely. As vav suggested, locks from other sources could cause an indefinite wait.
Related
I have an old intranet website written with vb.net and using Oracle.ManagedDataAccess mostly doing read operations from Oracle database 11g.
My db connection code is as follows.
Public Shared Function MyDBConnection(ByVal command_text As String, ByVal connstring As String, ByVal ParamArray parameters As OracleParameter()) As DataTable
Dim OraCommand As New OracleCommand
Dim tmp As New DataTable
Using ORAconnection = New OracleConnection(ConfigurationManager.ConnectionStrings(connstring).ConnectionString)
OraCommand.CommandText = command_text
If parameters IsNot Nothing AndAlso parameters.Length > 0 Then
For Each p In parameters
OraCommand.Parameters.Add(p.ParameterName, p.OracleDbType, p.Size).Value = p.Value
Next p
End If
OraCommand.Connection = ORAconnection
Try
ORAconnection.Open()
tmp.Load(OraCommand.ExecuteReader())
Catch ex As OracleException
End Try
End Using
Return tmp
End Function
And my oracle connection string is like this
<add name="ConnectionString" connectionString="User Id=userid;Password=userpadd;Data Source=servername:port/port_dp"/>
I was testing if my connections to the database were closing properly but it looks like connections on the database stayed open after being closed on my code. Eventually they close way after my query completed about 2 minutes, 10 minutes or hours later.
Is this connection pooling at work? or if there is something wrong with my code?
After reading about oracle pooling, it looks like the application should be reusing the same opened connection on the DB but in my case it looks like is opening new connections anyway.
So my question is, should I disable pooling on my connection string to make sure all connections open/close and not have connections lingering on the DB?
No, you should not disable connection pooling. In .NET connection pooling is managed by a mechanism outside of your reach, and you should proceed as if it is not there: open and close your connections as you normally would (i.e. at the beginning and end of every set of operations that you wish to enroll in a transaction/every set of ops that defines a good "unit of work" such as running a report, updating a table etc
The action of opening and closing connections in your code simply leases the from/returns them to the pool. .NET will manage the rest regarding maintaining a cache of some open connections to the db
Yes, there's pooling. The number of connection might have to do with the default value of min and max pool size. Also, OracleCommand does have a Dispose method that you are not calling.
Added: I see your empty catch statement, you don't need it when using "Using" (or ever). The Dispose will still be called if there's an exception.
Is there any benefit to explicitly using the StoredProcedure CommandType as opposed to just using a Text Command? In other words, is
cmd = new SqlCommand("EXEC StoredProc(#p1, #p2)");
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#p1", 1);
cmd.Parameters.Add("#p2", 2);
any worse than
cmd = new SqlCommand("StoredProc");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#p1", 1);
cmd.Parameters.Add("#p2", 2);
EDIT: Fixed bad copy paste job (again). Also, the whole point of the question is for a data access class. I'd much rather be able to pass the stored proc name and parameters in one line as opposed to extra lines for each parameter.
One difference is how message pumping happens.
Where I used to work we had a number of batch processes that ran over night. Many of them simply involved running a stored procedure. We used to schedule these using sql server jobs, but moved away from it to instead call the procedures from a .Net program. This allowed us to keep all our scheduled tasks in one place, even the ones that had nothing to do with Sql Server.
It also allowed us to build better logging functionality into the .Net program that calls the procedures, so that the logging from all of the overnight processes was consistent. The stored procedures would use the sql print and raiserror functions, and the .Net program will receive and log those. What we learned was that CommandType.StoredProcedure would always buffer these messages into batches of about 50. The .Net code wouldn't see any log events until the procedure finished or flushed the buffer, no matter what options you set on the connection or what you did in your sql. CommandType.Text fixed this for us.
As a side issue, I'd use explicit types with your query parameters. Letting .Net try to infer your parameter types can cause issues in some situations.
It's cleaner.
You're calling a stored procedure, why not just use the CommandType.StoredProcedure?
I have a SP which takes 20 seconds in SqlServer environment but sometimes in my ASP.NET page when I run the SP I get SqlServer timeout excaption.
I event set CommandTimeout and ConnectionTimeout to 60 but I still get the exception.
I would appreciate to help me.
Some other operation might be locking the table. set the timeout to a higher value and check.
while running the proc execute sp_lock and sp_who2 system procedure for any locking
You can try
cmd.CommandTimeout = 0;
if you are executing a query taking long time.
1) tried something like??
SqlCommand cmd = new SqlCommand("MyReport", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 3660; //// or set it zero (0)
2) and this???
3) Assuming your db server and point of execution are different, is your internet/intranet connectivity fine?
4) check for vpn connection (if used)
Execute the query from the SSMS and save the execution plan. Then run the application and have the SQL Profiler to capture the trace and then save the execution plan from profiler as mentioned in this link.
Compare the two execution plan to find out the actual difference in execution.
Check for parameter sniffing. If you still have the issue make sure the DB statistics are updated, sometimes this might be the issue after that drop and create the procedure.
I think the problem is the sending parameters from your application to store procedure.
try it again but this time use SQL Server Profiler to trace your query execution .
you can use TextData column value in SQL Server Profiler and run real executed query again to find the real problem.
I'm having a strange problem with IIS, asp.net and ODBC.
My application is driven by SQL server via ODBC driver (I know it's bad practice, but my entire DAL is already written and will not be changed).
The problem is that when I run an SP with my web interface, on any other computer other than the production server it works fine, but on the production server I get the following error:
Exception Message: System.Data.Odbc.OdbcException (0x80131937): ERROR [42000] [Microsoft] [ODBC SQL Server Driver][SQL Server]Error converting data type nvarchar to int
Obviously when I run it under management studio it works fine.
I think the problem is somewhere between the IIS and the odbc driver, but I'm not sure exactly where.
I'm running .net framework 4.
This is the calling method:
ODBCComm command = new ODBCComm();
command.Query = "SP_web_update_calls_dest #id=?,#name=? ,#ivrCode=?,#DDI=?,#destType=?,#trkGroup=?,#result=? output";
command.AddInputParam(id);
return AddParamsAndExecute(name, ivrCode, DDI, destType, trkGroup, command);
it basically wraps arround:
OdbcCommand.ExecuteDirect();
Thanks a lot,
Yuval.
I believe your first param is being used in the ID spot. I'm not sure why this would work in pre-production and fail only in production, but try this instead...
ODBCComm command = new ODBCComm();
command.Query = "SP_web_update_calls_dest #id=?,#name=? ,#ivrCode=?,#DDI=?,#destType=?,#trkGroup=?,#result=? output";
return AddParamsAndExecute(id, name, ivrCode, DDI, destType, trkGroup, command);
I have no idea what ODBCComm is or what AddParamsAndExecute does because you haven't included the relavant code, however, here's what the request should look like:
OdbcCommand Cmd = new OdbcCommand("SP_web_update_calls_dest", _Connection);
Cmd.CommandType = CommandType.StoredProcedure;
Cmd.Parameters.Add("#id", OdbcType.Int);
Cmd.Parameters["#id"].Value = id;
Cmd.Parameters.Add("#name", OdbcType.NVarChar);
Cmd.Parameters["#name"].Value = name;
Cmd.Parameters.Add("#ivrCode", OdbcType.Int);
Cmd.Parameters["#ivrCode"].Value = ivrCode;
Cmd.Parameters.Add("#DDI", OdbcType.VarChar);
Cmd.Parameters["#DDI"].Value = DDI;
Cmd.Parameters.Add("#destType", OdbcType.Int);
Cmd.Parameters["#destType"].Value = destType;
Cmd.Parameters.Add("#trkGroup", OdbcType.Int);
Cmd.Parameters["#trkGroup"].Value = trkGroup;
Cmd.Parameters.Add("#result", OdbcType.Int);
Cmd.Parameters["#result"].Direction = ParameterDirection.Output;
Cmd.ExecuteNonQuery();
int result = (int)Cmd.Parameters["#result"].Value;
OK,
I think I solved it.
There were actually 2 problems, and I'm not exactly sure what caused them.
Anyway, I switched the ODBC driver to SQL Server Native Client 10.
This basically solved the problem, but for some reason it doesn't support the output modifier in queries so I had to remove that.
So I got it solved, but still have no idea what caused the problem. I'm guessing it has something to do with different versions of drivers.
I'm having difficulty with an SQL query against Server 2008 from IIS7. I have a VB.NET class library which runs an update statement. The underlying code used to create the connection hasn't changed, but suddenly the query is failing in our testing and development environments. It does, however, still work against the same server/database using the slightly older code in our production environment.
I've tried setting the connection timeout in the web.config and I'm at a loss to explain the cause.
The basic structure of the query is:
Dim conn = New SqlConnection()
conn.ConnectionString = "Data Source=someserver\sqlexpress2008;Initial Catalog=DatabaseName;User ID=sa;Password=pass"
conn.Open()
Using cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "UPDATE ..."
cmd.Parameters.AddWithValue("#UName", user.name)
cmd.ExecuteNonQuery() 'fails with error
End Using
The error is:
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.)
I've tried restarting IIS and the SQL server and I'm totally out of ideas. I just need a fix
You need to open the connection before calling SqlCommand.ExecuteNonQuery(). You do this by calling SqlConnection.Open().
Dim conn = New SqlConnection()
conn.ConnectionString = "Data Source=someserver\sqlexpress2008;Initial Catalog=DatabaseName;User ID=sa;Password=pass"
Using cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "UPDATE ..."
cmd.Parameters.AddWithValue("#UName", user.name)
conn.Open()
cmd.ExecuteNonQuery() 'fails with error
conn.Close()
End Using
Also, ensure you database isn't in single user mode.
This helped another person who was stuck recently. You could examine the problem from the database server by setting up a SQL Server Profiler.
You can find lots of info about SQL Profiler by just googling around. Here's a site with a video that might help you get started. For starters, you would be able to see if the request is even reaching the database server.
This was a nightmare to track down. It turned out to be cause by a horrible quirk in VB.NET. Nullable datetimes seem to be coerced to DateTime.MinValue, which resulted in a DateTime.MinValue being inserted into an sql datetime. The fix was to check for either !property.HasValue && property.Value != DateTime.MinValue when setting the parameters for the command.
This is a network-level error. The database server is killing the connection for some reason. In order to troubleshoot this, I would open a connection using SSMS to the DEV and TEST servers and make sure that I can run simple queries w/o problems. It's unlikely that the issue is your library since you would be getting timeout or some other kind of errors.
as Lcarus, said, database server is killing the connection for unknown reason.
you can check the logs, to verfiy. Log path will be C:\Program Files\Microsoft SQL Server\<your instance>\MSSQL\LOG
from MSDN Blog MSDN Blog
this will occur when A connection is taken from the connection pool,
the application does not know that the physical connection is gone, an
attempt to use it is done under the assumption that the physical
connection is still there.