what is the best way to call a stored procedure and still have a very low response time in asp.net ? i have tried filling a dataset from an adapter:
SqlConnection conn = new SqlConnection(dbm.ConnectionString);
SqlCommand sqlcom = conn.CreateCommand();
sqlcom.CommandType = CommandType.StoredProcedure;
sqlcom.CommandText = "";
sqlcom.Parameters.Add(new SqlParameter("#SOME_ID", Session[IWConstants.SessionAccountID]));
sqlcom.Parameters.Add(new SqlParameter("#END_DATE", ""));
sqlcom.Parameters.Add(new SqlParameter("#FILTER_OPTION", ""));
sqlcom.Parameters.Add(new SqlParameter("#START_DATE", ""));
SqlDataAdapter sqlDA = new SqlDataAdapter(sqlcom);
DataSet ds = new DataSet();
sqlDA.Fill(ds);
csvDataTable = ds.Tables[0];
and this block is giving me 11,000 plus milli seconds in response is there a better way of doing it ??
What you have written is definitely one of the most efficient ways. I assume that you acrually set the CommandText to the name of your stored procedure.
Your response time probably has to do with either network topology or available sql server resources. (Assuming your sp excutes on very short time when tested directly on the sql server.)
Check out the second table on this page http://ormeter.net/ to see how much an ORM adds to execution time if that is what you are considering that as an option.
If you want to micro-optimize what happens in client code you could use a datareader instead of filling a dataset. That has slightly lower overhead, but in comparison to accessing the database it's usually negligable.
Related
I am setting CommandTimeout to 1 second and no TimeoutException is being thrown as expected. The query I am running takes about 7-8 seconds. The timeout does work however when I use ExecuteReader to execute a query rather than trying to fill a DataTable. I have tried setting CommandTimeout when after creating the command and also after creating the DataAdapter.
using(SqlConnection con = new SqlConnection("data source=*****;user id==*****;password==*****;initial catalog==*****;"))
{
string query = "select * from *****";
SqlCommand command = new SqlCommand(query, con);
//command.CommandTimeout = 1;
CostingDataSet cds = new CostingDataSet();
SqlDataAdapter da = new SqlDataAdapter(command);
da.SelectCommand.CommandTimeout = 1;
Stopwatch stopwatch = Stopwatch.StartNew();
da.Fill(cds.CostingData);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
The cause is the magic that occurs in the SQLDataAdapter, which is frankly, why they are a bad idea.
My guess is they are using async to perform the fill, which will always ignore command timeouts.
My suggestion: run away from the adapter, and never look back. They aren't that valuable and make everything messier.
If that isn't possible, set your connection timeout in your connection string and it should apply regardless of how the db is accessed.
Queries like "select * from" are a bad idea.
What is the reason not to use select *?
That said, maybe you could restric the amount of data to return, by paging or similar way. Reducing the amount of returned data will make it work
I am trying to insert bulk records in a sql server database table using dataset. But i am unable to do transaction handling. Please help me to apply transaction handling in below code.
I am using adapter.UpdateCommand.Transaction = trans; but this line give me an error of Object reference not set to an instance of an object.
Code:
string ConnectionString = "server=localhost\\sqlexpress;database=WindowsApp;Integrated Security=SSPI;";
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
SqlTransaction trans = conn.BeginTransaction(IsolationLevel.Serializable);
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Test ORDER BY Id", conn);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.UpdateCommand.Transaction = trans;
// Create a dataset object
DataSet ds = new DataSet("TestSet");
adapter.Fill(ds, "Test");
// Create a data table object and add a new row
DataTable TestTable = ds.Tables["Test"];
for (int i=1;i<=50;i++)
{
DataRow row = TestTable.NewRow();
row["Id"] = i;
TestTable .Rows.Add(row);
}
// Update data adapter
adapter.Update(ds, "Test");
trans.Commit();
conn.Close();
If the data-adapter doesn't make it easy to pass in a transaction, and doesn't handle it internally, then you might be able to force it by using TransactionScope instead - since this is ambient rather than explicit.
However! My main guidance here would be more simple: stop using data-sets and data-adapters. They were essentially hangover from pre-.NET patterns, and were handy when the data tooling for .NET was in an early state. It is no longer in that state. Virtually any other data access tool would be preferable.
I could not test your code, but I think you should also pass the connection of the trans object to your adapter like in the following example:
...
adapter.UpdateCommand.Connection = trans.Connection;
adapter.UpdateCommand.Transaction = trans;
...
Good luck!
Source: CodeProject
Through designer I have created a typed data set and included stored procedures for insert / update / delete. The problem is now, how to call those stored procedures? How to actually change data in database this way? And how to receive answer from db (number of rows changed)?
try this for get data from database.
DataSet ds = new DataSet("dstblName");
using(SqlConnection conn = new SqlConnection("ConnectionString"))
{
SqlCommand sqlComm = new SqlCommand("spselect", conn);
sqlComm.Parameters.AddWithValue("#parameter1", parameter1value);
sqlComm.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = sqlComm;
da.Fill(ds);
}
Similarly you need to call "spdelte" etc.
I found out that far easiest way is through designer - create table adapter and simply set it to call stored procedure. No extra typing needed, arguments are also added to procedure call.
We've been given a "stored procedure" from our RPG folks that returns six data tables. Attempting to call it from .NET (C#, 3.5) using the iSeries Provider for .NET (tried using both V5R4 and V6R1), we are seeing different results based on how we call the stored proc. Here's way that we'd prefer to do it:
using (var dbConnection = new iDB2Connection("connectionString"))
{
dbConnection.Open();
using(var cmd = dbConnection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "StoredProcName";
cmd.Parameters.Add(new iDB2Parameter("InParm1",
iDB2DbType.Varchar).Value = thing;
var ds = new DataSet();
var da = new iDB2DataAdapter(cmd);
da.Fill(ds);
}
}
Doing it this way, we get FIVE tables back in the result set. However, if we do this:
cmd.CommandType = CommandType.Text;
cmd.CommandText = "CALL StoredProcName('" + thing + "')";
We get back the expected SIX tables.
I realize that there aren't many of us sorry .NET-to-DB2 folks out here, but I'm hoping someone has seen this before.
TIA.
Look into the LibraryList (and maybe the Naming) property of your connection string. When you use CommandType.StoredProcedure it could be executing the stored procedure right from the SQL database library. When you use CommandType.Text it searches the library list to find the stored procedure. You end up running different versions of the stored procedure from different libraries which gives you different results.
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....