I have an application which is written in asp.net and C#. I am using a class with Connected mode for Insert/Update and delete statements. I have proper try, catch and Finally statements which is opening and closing the OracleConnection. But still sometimes its just getting out without closing the connection and is making locks in the DataBase, which in turn makes the website stop.
Now i thought to change the Queries into a Disconnected mode where the DataAdapter will manage the connection issues. I need to execute custom Queries with parameters.
I wrote an application where i tried calling INSERT/UPDATE/DELETE statements using DataAdapter objects FILL method. Its working fine.(For da.Update() method it needs a row and row state etc which i thought will be tough)
I want to know will there be any issues in performance of database or in the application if i use this method??
int i = 0;
using (OracleConnection con = new OracleConnection(WebConfigurationManager.ConnectionStrings["MYSTRING"].ConnectionString))
{
OracleCommand cmd = new OracleCommand("INSERT INTO MYTABLE(ID) VALUES(:ID)", con);
cmd.Parameters.AddWithValue(":ID", 123);
using (OracleDataAdapter da = new OracleDataAdapter(cmd))
{
i = da.Fill(new DataSet());
}
cmd.Dispose();
}
return i;
The above code runs any query(insert,update,delete) which is sent to the DataAdapter. Should i do it in any other way or will this be ok??
I don't know about OracleCommand Objects, but in SqlDataAdapter you have Insert Command, DeleteCommand, UpdateCommand. DataAdapterProperties or else you can use IdbDataAdapter Interface IDbDataAdapter Interface
yourDataAdapter.InsertCommand = YourInsertCommandObject;//
for Update
yourDataAdapter.UpdateCommand = YourUpdatcommand;
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.
Here's what I got: User selects from a checklistbox of database names one they'd like to archive. Switch case in place to catch the selection.
case "userSelection":
sqlAdapter = CreateMyAdapter("dbName", true, sqlconn, null);
sqlAdapter.SelectCommand.CommandText += "";
sqlAdapter.Fill(myDS.tableName);
sqlAdapter.Dispose();
The adapter:
private SqlDataAdapter CreateMyAdapter(string TableName, bool IncludeUpdates, SqlConnection sqlConn, SqlTransaction sqlTran)
{
SqlDataAdapter sqlAdapter = null;
SqlConnection sqlConnArchive = new SqlConnection();
strSQL = "SELECT " + TableName + ".* FROM " + TableName;
sqlAdapter = new SqlDataAdapter(strSQL, sqlConn);
// Right here, I create another sqlConnection that is pointed to
// another datasource.
sqlConnArchive = getThisOtherConnection();
SqlCommand sqlComm;
if (IncludeUpdates)
{
string strInsertSQL = "<insertQuery>";
sqlComm = new SqlCommand(strInsertSQL, sqlConnArchive);
sqlComm.Parameters.Add("#TableID", SqlDbType.Int, 0, "TableID");
// More params here...
sqlAdapter.InsertCommand = sqlComm;
// Update
// Delete
}
}
return sqlAdapter;
The issue:
As you can see sqlConn is the connection that is tied to the SELECT command. And sqlConnArchive is tied to the INSERT. The thought here is that I could select the data from DB_1 if you will, and insert it into DB_2 using the same SQLDataAdapter. But the issue that I'm running into is trying to insert. The select works fine, and at this line sqlAdapter.Fill(myDS.tableName); once fill executes the data is there. But the INSERT isn't working.
A few things:
I tested to see if perhaps SQLDataAdapter couldn't handle multiple datasources/connections, switched things around so it was pointing the the same DB just different tables, and I'm seeing the same results.
I've confirmed that the issue does not reside within the INSERT query.
There are no errors, just steps right over in debug.
I have tried several permutations of .Update() and none of them worked. This project that I've been assigned, throughout the entire thing it appears that .Fill(); is what is submitting the data back to the DB.
I've tested the database side and connectivity is a go. No issues with login, etc etc..
Any help is greatly appreciated.
Please note - I tried to place an even larger emphasis on the word "greatly" but was limited by my toolset. Apparently SOF doesn't support bold, blink, underline, flames, or embedded music.
I think you want ExecuteNonQuery.
var rowsAffected = sqlAdapter.InsertCommand.ExecuteNonQuery();
This executes the statement and then returns the number of rows affected. The Fill method won't run any InsertCommands.
I'm trying to save a note into the database by user input but my code isn't saving it to the Database.
I'm planning on checking the user input aswell with functions.
SqlConnection con = database.GetConnection();
SqlCommand command = new SqlCommand("INSERT INTO notities (notities_gebruiker, notities_datum, notities_doeldatum, notities_bericht) values(#notities_gebruiker, #notities_datum, #notities_doeldatum, #notities_bericht)", con);
command.Parameters.AddWithValue("#notities_gebruiker", this.gebruikerid.ToString());
command.Parameters.AddWithValue("#notities_datum", DateTime.Now);
command.Parameters.AddWithValue("#notities_doeldatum", DateTime.ParseExact(this.targetDate.Text, "dd/MM/yyyy", null));
command.Parameters.AddWithValue("#notities_bericht", this.Note.Text);
con.Open();
command.ExecuteNonQuery();
con.Close();
initialiseListBox();
What's happening is that whenever I close my application the database loses it's values saved and goes back to original state. I can add items manually though..
EDIT: It rolls back the rows I have added in via application but I am able to pull the data from the database I saved if I keep it running.
You're forgetting to commit the data you've just inserted. Use the SqlTransaction class to begin a transaction:
SqlTransaction myTransaction = con.BeginTransaction();
command.ExecuteNonQuery();
myTransaction.Commit();
It would be a good idea to make use of the Using statement to make sure your connection, command and transaction are disposed of once the code block has been complete, rather than manually calling Close() methods:
Using (SqlConnection con = database.GetConnection())
{
con.Open();
Using (SqlCommand command = new SqlCommand("sqlhere"))
{
Using (SqlTransaction myTransaction = con.BeginTransaction())
{
//your code here
}
}
}
SqlTransaction class:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction(v=vs.110).aspx
Neat article on using statements:
http://www.codeproject.com/Articles/6564/Understanding-the-using-statement-in-C
Look for a copy of your database containing the data in your bin/debug folder.
Best way to avoid this is to use a full path in your connection string and avoid |DataDirectory| while debugging
I am trying to get column information in C# from a SQL table on SQL Server. I am following the example in this link: http://support.microsoft.com/kb/310107 My program strangely gets hung up when it tries to close the connection. If the connection is not closed, the program exits without any Exceptions. Here's my code:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
Putting the SqlConnection inside a using block also causes the application to hang unless CommandBehavior.KeyInfo is changed to CommandBehavior.SchemaOnly.
using (SqlConnection connection = new SqlConnection(#"MyConnectionString"))
{
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast even here in the using
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
}
The table in question has over 3 million rows, but since I am only obtaining the Schema information, I would think this wouldn't be an issue. My question is: Why does my application get stuck while trying to close a connection?
SOLUTION: Maybe this isn't optimal, but it does work; I inserted a command.Cancel(); statement right before Close is called on connection:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
command.Cancel(); // <-- This is it.
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
I saw something like this, long ago. For me, it was because I did something like:
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader();
// here, I started looping, reading one record at a time
// and after reading, say, 100 records, I'd break out of the loop
connection.Close(); // this would hang
The problem is that the command appears to want to complete. That is, go through the entire result set. And my result set had millions of records. It would finish ... eventually.
I solved the problem by adding a call to command.Cancel() before calling connection.Close().
See http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610 for more information.
It looks right to me overall and I think you need a little optimization. In addition to the above suggestion regarding avoiding DataReader, I will recommend to use connection pooling. You can get the details from here :
http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854
Could you try this?
DataTable dt = new DataTable();
using(SqlConnection conn = new SqlConnection("yourConnectionString"))
{
SqlCommand cmd = new SqlCommand("SET FMTONLY ON; " + yourQueryString + "; SET FMTONLY OFF;",conn);
conn.Open();
dt.Load(cmd.ExecuteReader());
}
SET FMTONLY ON/OFF from MSDN seems the way to go
There is an specific way to do this, using SMO (SQL Server management objects)
You can get the collection of tables in the database, and then read the properties of the table you're interested in (columns, keys, and all imaginable properties)
This is what SSMS uses to get and set properties of all database objects.
Look at this references:
Database.Tables Property
Table class
This is a full example of how to get table properties:
Retrieving SQL Server 2005 Database Info Using SMO: Database Info, Table Info
This will allow you to get all the possible information from the database in a very easy way. there are plenty of samples in VB.NET and C#.
I would try something like this. This ensures all items are cleaned up - and avoids using DataReader. You don't need this unless you have unusually large amounts of data that would cause memory issues.
public void DoWork(string connectionstring)
{
DataTable dt = new DataTable("MyData");
using (var connection = new SqlConnection(connectionstring))
{
connection.Open();
string commandtext = "SELECT * FROM MyTable";
using(var adapter = new SqlDataAdapter(commandtext, connection))
{
adapter.Fill(dt);
}
connection.Close();
}
Console.WriteLine(dt.Rows.Count);
}
One of the problems I am having with c# is that there seems to be so much information online that I am having trouble finding the right answer to the most basic of questions.
I am trying to do something simple:
I have a button, I click it, it queries the database and populates a datagrid on my windows form.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection c = new SqlConnection("Data Source = (local); Integrated Security = true; Initial Catalog = pubs; ");
c.Open();
// 2
// Create new DataAdapter
SqlCommand cmd = c.CreateCommand();
cmd.CommandText = #" SELECT * FROM Authors ";
SqlDataReader reader = cmd.ExecuteReader();
dataGridView1.DataSource = reader;
dataGridView1.DataBind();
}
Error 1 'System.Windows.Forms.DataGridView' does not contain a definition for 'DataBind' and no extension method 'DataBind' accepting a first argument of type 'System.Windows.Forms.DataGridView' could be found.....
I am probably missing a "using directive" but which one? Multiple Google searches tell me how to bind a Yahoo RSS Feed to a gridview or provide various obscure details on "using directives".
Maybe I am using the SqlDataReader incorrectly. Should I be using SqlAdapter instead? What happened to all the good basic tutorials online for windows c# forms? A few months ago I found a couple great tutorials, but they seem to have lost their pageranking and I cannot find them anymore using basic google searches.
You're not missing a using directive; it's just that the WinForms DataGridView doesn't have a DataBind method. Just assigning DataSource is enough to get the binding to happen; you don't need to call a method as well.
However, I don't think you can assign a SqlDataReader as the DataSource. According to the DataSource property documentation in MSDN, the DataSource must be an IList, an IListSource, an IBindingList or an IBindingListView. You will probably instead need to load the data into a DataTable or DataSet (or an object data source populated using an object-relational mapper), and use that as the DataSource.
Try this instead:
using (SqlConnection conn = new SqlConnection("your connection string"))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(#"SELECT * FROM Authors", conn))
{
using (SqlDataAdapter adap = new SqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
adap.Fill(dt);
dataGridView1.DataSource = dt;
}
}
}
The DataGridView does not have a DataBind() method because it doesn't need one. Setting the DataSource property handles the binding for you. The using() blocks will automatically close and dispose of everything for you as well.
Note: you should replace "your connection string" with a valid connection string. I left yours out of my sample to avoid the horizontal scrollbars, and I'm not sure yours is valid anyway. You may get a runtime error when you run the code using your connection string. www.connectionstrings.com is a great resource for figuring out a valid connection string.
Update: instead of the nested using() blocks, you can also do it like this:
using (SqlConnection conn = new SqlConnection("..."))
using (SqlCommand cmd = new SqlCommand(#" SELECT * FROM Authors", conn))
using (SqlDataAdapter adap = new SqlDataAdapter(cmd))
{
conn.Open();
DataTable dt = new DataTable();
adap.Fill(dt);
dataGridView1.DataSource = dt;
}
I prefer the nested style, but it's "half of one, six dozen of the other" to me. Typically, I would encapsulate code like this into a class (called "DataGetter" or whatever) with a static method like:
public static DataTable GetData(string query)
{
// do all the connecting and adapting and filling and so forth
}
so that the code in your button click would be as simple as:
dataGridView1.DataSource = DataGetter.GetData("SELECT * FROM AUTHORS");
However, I would not do this in any performance-critical section of my code, since you sometimes want to keep a SqlCommand object (and its SqlParameter collection) around between calls. You do not need to keep SqlConnection objects around between calls, thanks to connection pooling (in fact, you don't want to keep them around under any circumstances).