I'm curious if there is a difference, if any between adding Parameters to the OracleCommand and then adding them to the OracleDataAdapter or by directly adding them to the OracleDataAdapter?
For example,
Adding them to the OracleCommand and then linking them to the OracleDataAdpater
string f= "foo";
string sql = "SELECT #c FROM Dual";
using(OracleCommand command = new OracleCommand(sql, this.Connection))
{
OracleParameter param = new OracleParameter("#c", f);
command.Parameters.Add(param);
OracleDataAdapter adapter = new OracleDataAdapter(command);
adapter.SelectCommand = command;
DataSet dataset = new DataSet();
adapter.Fill(dataset);
return dataset;
}
Adding them directly to the OracleDataAdapter
string f= "foo";
string sql = "SELECT #c CalcVarValue FROM Dual";
using(OracleCommand command = new OracleCommand(sql, this.Connection))
{
OracleDataAdapter adapter = new OracleDataAdapter(command);
adapter.SelectCommand.Parameters.Add(new OracleParameter("#c", f));
DataSet dataset = new DataSet();
adapter.Fill(dataset);
return dataset;
}
Is one way more preferred over the other? Is adding to the OracleDataAdapter directly faster in execution compared to the other method?
There is no difference whatsoever. In both cases, the parameter is added to the OracleCommand.
Choosing between these two coding styles is a matter of personal preference, coding conventions you are obligated to (if exists) and mostly, opinion.
Personally, I tend to go with the shortest possible code that you can still read a year from the day you wrote it and understand what it does without having to think about it, or as someone once wrote (I think it was on Meta.SE) - In this industry, you should write your code as simple as possible, because the person that will take over the project after you will most likely be an idiot.
Related
I am running into a problem where it prompts me an error that says "Must declare the scalar variable "#ID". This only happens when when I add the parameter in, but when I add the variable in, it works fine.
Down below is the code that gives me the problem:
cmd.CommandText = "Select * From Attendee WHERE ID=#ID";
cmd.Connection = conn;
cmd.Parameters.AddWithValue("#ID",ID);
conn.Open();
cmd.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter(cmd.CommandText,cmd.Connection);
da.Fill(dt);
conn.Close();
When I just add in the variable such as:
cmd.CommandText = "Select * From Attendee Where ID=" + ID;
It works perfectly fine.
In the SqlDataAdapter constructor you pass the SqlCommand.CommandText.
This text (just a string) is not enough to define the parameter #ID that is defined instead in the SqlCommand.Parameters collection
You have two options
SqlDataAdapter da = new SqlDataAdapter(cmd.CommandText,cmd.Connection);
da.SelectCommand.Parameters.AddWithValue("#ID",ID);
da.Fill(dt);
or just build your adapter using the command
SqlDataAdapter da = new SqlDataAdapter(cmd);
As an added advice, I really suggest you to not use AddWithValue, but instead use the overload of Add that takes also the type for the parameter
cmd.Parameters.Add("#ID",SqlDbType.Int).Value = ID;
See Can we stop using AddWithValue already?
I'm accessing a table from my database. I have added the tables as a dataset in Visual Studio 2013, but when I try to use it, it comes out empty.
This is what I'm trying to do:
IQueryable<NorthwindDataSet.OrdersRow> LookupOrdersForYear(int year)
{
using (var context = new NorthwindDataSet())
{
var orders =
from order in context.Orders
where order.OrderDate != null && order.OrderDate.Year >= year
select order;
return orders.ToList().AsQueryable();
}
}
I found out that orders was empty, so I added
Console.WriteLine(context.Orders.Count);
which gave me an output of 0. What went wrong?
I found out that I needed to fill my dataset with data, or it would stay empty.
A SqlDataAdapter did the trick:
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand("SELECT * FROM Orders");
string connString = #"Data Source=localhost\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True";
SqlConnection conn = new SqlConnection(connString);
adapter.SelectCommand = command;
adapter.SelectCommand.Connection = conn;
adapter.Fill(context.Orders);
There are several overloaded methods for SqlDataAdapter.Fill, of which one takes a dataset and another takes a datatable. When I first used the SqlDataAdapter, I used the one that takes a dataset
adapter.Fill(context);
which still gave me an empty context.Orders. The correct one takes a datatable:
adapter.Fill(context.Orders);
This one worked and returned the dates as expected.
Trying to improve my C# to SQL skills... Currently I am using this bit of code to pull data from our application server. I have two different DBA's telling me two other ways to write this, just trying to figure out if this should be improved on or changed. If so, I would really appreciate some kind of examples.
FYI: This code...
db.con(user.Authority)
...Is essentially a 'new sqlconnection' code.
DataTable dtInfo = new DataTable("SomeInfo");
using (SqlConnection con = db.con(user.Authority))
{
string command = "SOME SQL STATEMENT;";
using (SqlCommand cmd = new SqlCommand(command,con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
con.Open();
cmd.ExecuteNonQuery();
**********
*** OR ***
**********
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dtInfo );
}
}
}
So, if I'm understanding the provided information, this is my best route?
using (SqlConnection con = db.con(user.Authority))
{
string command = "SELECT [TBL_EMPLOYEE].[ACTIVE_DIRECTORY] FROM [TBL_EMPLOYEE];";
using (SqlCommand cmd = new SqlCommand(command, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
MessageBox.Show(reader["ACTIVE_DIRECTORY"].ToString());
}
}
}
And one last thing... This should prevent the need for
cmd.Dispose();
etc...
The code would depend on the specific query. If the query retrieves rows of data (as a SELECT does), then you would go the da.Fill() route. If it's a query that just makes a change to the database (such as INSERT, UPDATE, or DELETE), then you would use ExecuteNonQuery().
I would not use the SqlDataAdapter version. The version that uses the SqlCommand object and the SqlDataReader will perform better, and allows more insight into the actual data being returned.
// Assumes the following sql:
// SELECT foo, bar FROM baz
// error checking left out for simplicity
var list = new List<SomeClass>();
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {
list.Add(new SomeClass {
// NOTE: you can see the columns that the c# is referencing
// and compare them to the sql statement being executed
Foo = (string)reader["foo"],
Bar = (string)reader["bar"]
});
}
}
Later as your level of experiance increases you will be able to use other features of the SqlCommand and SqlDataReader classes in order to ensure that the code executes as quickly as possible. If you start using the SqlDataAdapter route, you will eventually have to relearn how to do the exact same things you have already been doing because the SqlCommand and SqlDataReader have operations that do not exist elsewhere in .NET.
ExecuteNonQuery returns the number of rows effected.
A DataTable is not an efficient way to retrieve that number.
int rowsRet = cmd.ExecuteNonQuery();
SqlCommand.ExecuteNonQuery Method
conn = new SqlConnection(#"Data Source=ASHISH-PC\SQLEXPRESS; initial catalog=bank; integrated security=true");
ada = new SqlDataAdapter("select total_amount from debit_account where account_no=12", conn);
ds = new DataSet();
ada.Fill(ds);
Now, I want to print value of the dataset... how? Please help me.
I'd suggest that the best option here isn't actually a SqlDataAdapter and DataSet, but rather a SqlCommand. Try this:
using(SqlConnection conn = new SqlConnection(#"Data Source=ASHISH-PC\SQLEXPRESS; initial catalog=bank; integrated security=true"))
{
conn.Open()
using (SqlCommand command = new SqlCommand("select total_amount from debit_account where account_no=12", conn)
{
var result = command.ExecuteScalar();
Console.WriteLine("The total_amount for the account is {0}", result);
}
}
The ExecuteScalar() method on SqlCommand returns the value in the first column of the first row that your query returns, which is ideal in this situation.
If you absolutely have to use a dataset then you'd want to do the following:
using(SqlConnection conn = new SqlConnection(#"Data Source=ASHISH-PC\SQLEXPRESS; initial catalog=bank; integrated security=true"))
{
conn.Open()
using (SqlDataAdapter adapter = new SqlDataAdapter("select total_amount from debit_account where account_no=12", conn)
{
var ds = new DataSet();
adapter.Fill(ds);
Console.WriteLine("The total_amount for the account is {0}", ds.Tables[0].Rows[0][0]); // Get the value from the first column of the first row of the first table
}
}
Note: I've wrapped both examples in the C# using statement, this ensures that all your database resources are cleaned up so you don't have any problems with with leaking unmanaged resources. It's not particularly difficult or complicated so is well worth doing
I think, in this case, you'd be better off (performance-wise) to use a SqlCommand instead of the adapter and dataset, and invoke the ExecuteScalar method.
See http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
If you must use the data set, however, ds.Tables[0].Rows[0]["total_amount"] should retrieve your value. You will probably need to type cast the value, though.
I have a data adapter. When I check the function at runtime I see the changes, but nothing happens in the database. How do I debug this? What went wrong?
OleDbDataAdapter adapter = new OleDbDataAdapter();
string queryString = "SELECT * FROM tasks";
OleDbConnection connection = new OleDbConnection(cn.ConnectionString);
adapter.SelectCommand = new OleDbCommand(queryString, connection);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
connection.Open();
adapter.Fill(ds.Tables["Tasks"]);
adapter.Update(ds);
return ds;
Nothing is happening in the database because you're running a SELECT query. What are you expecting to happen?
Well unless you snipped a lot of code, you are not changing anything in the dataset per se.
What are you trying to achieve?
Here, you are selecting some data, filling the dataset with it, then putting back the unchanged dataset in the DB.
You should first change something in the dataset itself before calling adapter.Update(ds)
Cheers,
Florian
You are selecting data via the SelectCommand. If you want to update data, you need to run the UpdateCommand.
I assume you didn't post the full source code, as it looks as though you're not modifying the dataset. However, I just tweaked your code a bit (see my comments).
Hopefully this will help...
string queryString = "SELECT * FROM tasks";
OleDbConnection connection = new OleDbConnection(cn.ConnectionString);
connection.Open(); // open connection first
SqlCommand cmd = new SqlCommand(queryString, connection);
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd); // use the cmd above when instantiating the adapter
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
adapter.Fill(ds.Tables["Tasks"]);
// Modify your dataset here.
// Don't call AcceptChanges() as this will prevent the update from working.
adapter.Update(ds);
connection.Close(); // Close connection before ending the function
return ds;
This should allow OleDbCommandBuilder to do its thing by automatically scripting the database updates.
As far as I can see you've not actually changed any of the contents of the tasks table. When you call adapter.Fill you are populated the empty dataset with the records from the database. You are then calling adapter.Update without changing any records within the dataset. The update command only performs changes when the dataset > datatable > datarows are edited and marked as dirty.
you are only specifying the select command. you also need to specify the insert command... i.e:
DataAdapter.InsertCommand = new OleDbCommand....