I am using C# + .Net 3.5 + VSTS 2008 + ADO.Net + SQL Server 2008. And I am sharing one single SQL Connection object (TestDBConnection variable in my below sample) within my application.
The exception I met with is, "There is already an open DataReader associated with this Command which must be closed first.." Any ideas what is wrong?
The patterns within my application which I am using are all like this, i.e. sharing the single db connection object TestDBConnection, and using the single TestDBConnection variable to create command on it and execute store procedure.
using (SqlCommand testCommand = new SqlCommand())
{
testCommand.Connection = TestDBConnection;
testCommand.CommandType = CommandType.StoredProcedure;
testCommand.CommandText = "prc_AddOrderStatus";
testCommand.Parameters.Add("#orderID", SqlDbType.NVarChar).Value = orderID;
testCommand.ExecuteNonQuery();
}
thanks in advance,
George
Don't share the connection, use connection pooling instead. If you are doing two things at the same time on the connection, you might want to look into MARS.
For a test add this to your connection string: ;MultipleActiveResultSets=True; and see if this "fixes" the error. A lot of people believe you should avoid using MARS, so this is something to consider.
using (sqlConnection theconnection = new sqlconnection(initialise it))
{
using (SqlCommand testCommand = new SqlCommand())
{
testCommand.Connection = theConnection
testCommand.CommandType = CommandType.StoredProcedure;
testCommand.CommandText = "prc_AddOrderStatus";
testCommand.Parameters.Add("#orderID", SqlDbType.NVarChar).Value = orderID;
testCommand.ExecuteNonQuery();
}
}
is the pattern that i use in multi threaded cases with no problems at all.
Incidently this is connection pooling.
George, is it possible that the exception is telling you the truth? Are there any other commands that you've started but not yet finished?
Related
I am developing an asp.net web application and I am trying to add a user xp system to it. I have a SQL Server database connected to it and I am trying to make a function that will give 5 experience points to the user.
I queried to the user that is logged in, accessed the user_xp column, and I am trying to add +5 to the old session variable for xp, then send that back into the database to be stored. Here is my code, I am not sure what is wrong with it.
void generateXp()
{
try
{
SqlConnection con = new SqlConnection(strcon);
if (con.State == ConnectionState.Closed)
{
con.Open();
}
SqlCommand cmd = new SqlCommand("UPDATE member_master_tbl SET user_xp = #user_xp WHERE " +
"user_name = '" + Session["username"].ToString().Trim() + "'", con);
int xp = 5;
int current_xp = Convert.ToInt32(Session["user_xp"]);
int new_xp = xp + current_xp;
string new_xp2 = Convert.ToString(new_xp);
cmd.Parameters.AddWithValue("user_xp", new_xp2);
}
catch (Exception ex)
{
}
}
Try renaming the SQL parameter to #user_xp.
cmd.Parameters.AddWithValue("#user_xp", new_xp2);
I don't have an accessible database to test. Also, you need to add the command to execute the query at the end.
cmd.ExecuteNonQuery()
That being said, it's a good practice to learn to separate DB queries to stored procedures or functions.
As others noted, you simply forgot to do a execute non query to run the command that you setup.
However, you can write things this way. You don't mention or note what the data type the experience points column is - I assumed "int".
So, your code block can be written this way:
using (SqlCommand cmd = new SqlCommand("UPDATE member_master_tbl SET user_xp = #user_xp WHERE user_name = #user",
new SqlConnection(strcon)))
{
cmd.Parameters.Add("#user_xp", SqlDbType.Int).Value = 5 + Session("user_xp");
cmd.Parameters.Add("#user", SqlDbType.NVarChar).Value = Session("username");
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
note how the command object has a connection object (so we don't need a separate one).
And while several people here "lamented" the string concentration to build the sql and warned about sql injection?
Actually, the introduction of # parameters for both values cleans up the code. So you get nice parameters - nice type checking, and you don't have to remember to add/use/have things like quotes around teh string, but not for numbers.
And I let .net cast the number expression from session() - this also likely is ok.
Also the "using block" also correctly cleans up the command object and also the connection object - so the using block is a good idea here.
I am new to consuming db2 from a .net application.
My connection string looks like this
Server=myAddress:myPortNumber;Database=myDataBase;UID=myUsername;PWD=myPassword;
I am opening the connection and calling a stored procedure with success
using (OdbcConnection connection = new OdbcConnection(connectionString) )
using (OdbcCommand command = connection.CreateCommand())
{
command.CommandText = commandText;
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#KundenEmail", OdbcType.NChar, 50).Value = KundenEmail
DataTable dataTable = new DataTable();
connection.Open();
using (OdbcDataAdapter adapter = new OdbcDataAdapter(command))
{
adapter.Fill(dataTable);
}
}
I still can't figure out how to set the correlation id(CORRID) to a fixed value.
Is there a way to do this in code or to set it through the parameters in the config file?
Any help would be welcome,
thanks in advance
(Specifically the thread CORRID)
THREAD DETAIL
PLAN
+ Thread: Plan=KO2PLAN Connid=DB2CALL Corrid=D821DM4S Authid=DB2PM
+ Attach: BATCH JOB Name=D821DM4S JOB Asid= 122
+ Package: DGO#SDOB Collection=KO2OM410
place a 'T' in front of command to view by tablespace, 'D' by database
iio
There's not a lot of documentation about it, but it looks like the "ProgramName" parameter of the connection string will set the Correlation ID. If you're using the DB2ConnectionStringBuilder class, you can set it using that class (the property is called "ProgramName" as well).
If you build your Connection String manually, you can add it like so:
Database=xxx;User ID=yyy;Password=zzz;ProgramName=YourCorrelationId
There is also a property on the DB2Connection class (ClientProgramName) that sets this as well.
In my testing, it seems like you need to set this before you open the connection.
Alright, I am new to Windows Service applications. I am trying to create a Windows Service application using C# on Visual Studio 2012 that runs SQL statements. I was under the impression that we needed to enter a connection string in the web.config file for my SQL statements to communicate with the server. But there is no web.config file in a service application. How do I go about doing this? Any links to a tutorial or a tutorial in itself would be appreciated! I want to know the project structure and what I need to do for my application to work right.
Also, I have some SQL queries that need to run on multiple servers. The same queries run on 3 different servers. Does creating 3 connection strings and connecting to the 3 servers and running them the way to do it?
First of all, all applications have either a web.config or an app.config. If you are writing an MVC application or a Web Forms applications, then there is a web.config file. If you are writing a Windows service or a Windows Console or Desktop application, you'll have an app.config file instead.
Connecting to SQL Server is a pretty simple task. You just create a connection using SqlConnection. Next, you create a SqlCommand. Finally, you can execute your SQL query.
Here is an example:
public void DeleteRow()
{
using (var connection = new SqlConnection("your connection string here..."))
{
using (var command = new SqlCommand())
{
command.Connection = connection;
// Next command is your query.
command.CommandText = "DELETE FROM Customers WHERE CustomerId = 1";
command.CommandType = CommandType.Text;
connection.Open();
command.ExecuteNonQuery();
}
}
}
Use that first example if you are executing queries that return no data. If you need to return data, then use an example like this:
public void GetCustomer()
{
using (var connection = new SqlConnection("your connection string here..."))
{
using (var command = new SqlCommand())
{
SqlDataReader reader;
command.Connection = connection;
// Next command is your query.
command.CommandText = "SELECT * FROM Customers WHERE CustomerId = 1";
command.CommandType = CommandType.Text;
connection.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
}
}
}
I have a simple windows service and within this service I'm trying to connect to a sql server in a timer block (I tried to do that only once in onStart method -> same result).
For the moment I'm trying just to execute a select, using the following code:
using (SqlConnection sc = new SqlConnection())
{
var sqlConnection = new SqlConnection(_sqlConnectionString);
string commanda = "SELECT Moneda, SimbolMoneda FROM NomMoneda WHERE Moneda != '' AND SimbolMoneda != ''";
SqlCommand command = new SqlCommand(commanda, sqlConnection);
command.CommandType = System.Data.CommandType.Text;
IDataReader reader;
sc.ConnectionString = _sqlConnectionString;
sc.Open();
reader = command.ExecuteReader(CommandBehavior.CloseConnection);
}
I attached the service to debug, and I noticed that it didn't pass by this line of code sc.Open().
The service is not on the same machine as the sql server, but I have tried to install it under different users, LocalSystem, NetworkService, user within the same domain with the sql server, but with no result.
Any help would be appreciated.
It looks like you may have a logical error in this code. You are using sc for the SqlConnection, but when you create the command object you use sqlConnection, which is never actually opened.
This line is the problem:
SqlCommand command = new SqlCommand(commanda, sqlConnection);
Try the following instead:
SqlCommand command = new SqlCommand(commanda, sc);
EDIT at 10:22 following user comment
Just to confirm that you have made the change as indicated, I've re-jigged your code. Could you try the following:
using (SqlConnection sc = new SqlConnection())
{
sc.ConnectionString = _sqlConnectionString;
sc.Open();
string commanda = "SELECT Moneda, SimbolMoneda FROM NomMoneda WHERE Moneda != '' AND SimbolMoneda != ''";
SqlCommand command = new SqlCommand(commanda, sc);
command.CommandType = System.Data.CommandType.Text;
IDataReader reader;
reader = command.ExecuteReader();
}
I would expect that whatever the issue is it would be easier to figure out if you had a logging mechanism in place to catch and log unhandled exceptions. Due to the fact that Windows Services do not have a user interface you should implement logging from the beginning. Otherwise you will get to a point where the service terminates unexpectedly and what little information you gather from the system logs won't be enough to help you.
In short, add file logging and you'll probably figure out the issue immediately.
The problem was simple, but hard to detect. My connection string wasn't prefixed with the # char:
ex: _connectionString = #"Data Source =.......";
I have a weird 'bug/error', at the the .NET Connector only returns to me one record while there are 5 or something. The MySQL Command Line also returns 1. Here is the code I'm really stuck with this, I try to make a Client-Server and let the Client login from a DB at the Server Computer:
Code:
string strConnect = "server=localhost;user=root;password=xxxx;database=MoopleDEV";
string query = "SELECT name FROM accounts;";
using (MySqlConnection connection = new MySqlConnection(strConnect))
using (MySqlCommand command = new MySqlCommand(query, connection))
using (MySqlDataReader reader = command.ExecuteReader())
{
connection.Open();
while (reader.Read())
{
Console.WriteLine(reader.GetString("name"));
}
connection.Close();
}
Note: It also returns only 'iVision' at the MySQL Command Line Client. Anyone knows what to do?
Ps: It doesn't crash or return any exception.
IVision I hope that this will give you an idea
why are you using reader.GetString I have seen too many issues with that why not use the (string)reader["name"] approach also when you run the query how many rows are you returning when running the Query Manually also make sure that you are really looking at the right DB database=MoopleDEV could be incorrect or pointed to a different IP Address or location on your Physical Machine. I would also name my local Database Instance to an actual Name as well would cause less confusion
You are re-opening your connection after creating your reader. Move your connection open statement before you create your command object.
Try this instead:
using (MySqlConnection connection = new MySqlConnection(strConnect))
{
connection.Open();
using (MySqlCommand command = new MySqlCommand(query, connection))
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader.GetString("name"));
}
}
connection.Close();
}