This is related to the Nested Database transactions in C#.
The objects in collection I want to take in transaction implement their own transactions using SqlConnection.BeginTransaction method.
After reading this post I am not sure if I can mix those too or not.
I am using SQL Server 2005 and each object uses connection details from static configuration class.
Does anybody have experience with this ?
Here is the sample code:
using(TransactionScope scope = new TransactionScope())
{
for (int i=0; i<=1000....)
{
SqlConnection con = new SqlConnection()
SqlCommand cmd = new SqlCommand("delete from ...", con);
try {
con.Open();
DbTransaction t = con.BeginTransaction();
cmd.ExecuteNonQuery();
...
cmd.CommandText = .... ;
cmd.ExecuteNonQuery();
t.Commit ...
}
catch {
t.Rollback ...
}
con.Close()
}
}
Thx
After spending hours to configure MSDTC to work on both machines, I finally got to the point where I could test the code.
It appears to work (with 1 database)
The above problem may be usefull to people that don't have access to the source code so can't get rid of "legacy" transactional system or if transactional parts of the code are not localised or, like in my case, you don't want to mess too much with the complex code that is proven to be stable in production environment but you need to introduce nested transactions...
Let me know if you have different experience.
Related
I have a stored procedure that I need to run in C# and set the result set returning from the SP in a HTML table. Please note that the SP is working well in SSMS and returning results.
The c# code I am using is (it is in an ASP 4.5 project):
SQLDatabase sqldb = new SQLDatabase();
using (SqlConnection sqlcn = new SqlConnection(sqldb.GetConnectionString().ToString()))
{
if (sqlcn.State == ConnectionState.Closed)
{
sqlcn.Open();
}
SqlCommand cmd = new SqlCommand("[MyStoredProcedure]", sqlcn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#FromDate", Convert.ToDateTime(txtFrom.Value.ToString()));
cmd.Parameters.AddWithValue("#ToDate", Convert.ToDateTime(txtTo.Value.ToString()));
using (SqlDataAdapter a = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
a.Fill(ds);
dtExtra = ds.Tables[0];
}
}
This code above is returning 0 rows, even though the SP is working in SSMS. While debugging, the connectionstring and the parameters are coming all true, no issue. The connectionstring is:
<add name="DefaultDB" connectionString="Data Source=TestEnv;Initial Catalog=TestTable;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
I don't understand what may cause this. I found the topic below, but I am using Integrated Security=SSPI in my connection string already, so it did not help me. Any advice would be appreciated.
ASP.NET stored proc call bringing back no rows, but does in Management Studio!
EDIT: SOLVED! Thanks #NineBerry. It turned into a between/and usage problem in SP. Changing txtTo.Value as: DateTime.Today.AddDays(1).ToString("yyyy-MM-dd"); in the code fixed the issue (It was DateTime.Today.ToString("yyyy-MM-dd") before, I should have included it in the code part, didn't think it is related to that, sorry). Better solution would be updating the SP using >= and <= instead of between/and keywords tho.
I would modify your code to simply be:
using(var dbConnection = new SqlConnection("..."))
using(var command = new SqlCommand(query, dbConnection))
{
dbConnection.Open();
...
}
Handling the connection pooling in the using block is always a good idea per Microsoft guideline:
To ensure that connections are always closed, open the connection
inside of a using block, as shown in the following code fragment.
Doing so ensures that the connection is automatically closed when the
code exits the block.
You are checking if the connection is closed, what if the connection is idle? By using the using syntax you implement dispose. So it will correctly close your connection, so you should not need to check if the connection is closed unless you are using a singleton for the connection.
After reading your question, you may have more than just the one issue I pointed out. I would recommend a service account with access the specific data you are seeking, that the application can access rather than integrated security.
I would like to know what custom code (not EF) the experts use to get data from SQL Server in .NET / C#. I have been using methods like this:
public static DataTable SelectAllForNavigation()
{
using (SqlConnection sqlConn = new SqlConnection(Config.ConnStr))
{
try
{
SqlCommand sqlCmd = new SqlCommand("spr_Web_Content", sqlConn);
sqlConn.Open();
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.Add("#Op", SqlDbType.VarChar, 100).Value = "SelectAllForNavigation";
SqlDataReader sqlDr = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection);
DataTable dt = new DataTable();
dt.Load(sqlDr);
sqlDr.Close();
sqlDr.Dispose();
return dt;
}
catch (Exception)
{
return null;
}
}
}
It works and I don't see an overhead in SQL Server when hammering requests for data, but recently I have modified the method to this:
public static DataTable SelectAllForNavigation()
{
try
{
using (SqlConnection sqlConn = new SqlConnection(Config.ConnStr))
{
using (SqlCommand sqlCmd = new SqlCommand("spr_Web_Content", sqlConn))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.Add("#Op", SqlDbType.VarChar, 100).Value = "SelectAllForNavigation";
sqlConn.Open();
using (SqlDataReader sqlDr = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection))
{
DataTable dt = new DataTable();
dt.Load(sqlDr);
return dt;
}
}
}
}
catch (Exception)
{
return null;
}
}
Similar, but with 2 major differences; using using wrappers and placed a try/catch around the whole thing to try to catch any potential connection issues as well.
My questions are:
Is this new method that much better from an efficient perspective?
Where should the sqlConn.Open() be placed in the code?
Do I still need the CommandBehavior.CloseConnection in the SqlDataReader now that its wrapped with a using?
Any better way to do this, efficiently?
Is this new method that much better from an efficient perspective?
No, in terms of performance, the two approaches are probably almost identical. But your "new", second approach is much better in terms of maintainability and safety - it ensures that objects like SqlCommand etc. are freed as soon as possible.
Where should the sqlConn.Open() be placed in the code?
Just before you execute the query is really the best place for this - the connection really doesn't need to be open while you're doing all your setup work ....
Do I still need the CommandBehavior.CloseConnection in the SqlDataReader now that its wrapped with a using?
It's still a good idea, yes - even if the using block will also close the connection (when disposing the SqlCommand), I always find doing so explicitly in my own code is even better (and certainly doesn't hurt).
Any better way to do this, efficiently?
In terms of developer productivity : use Entity Framework to get rid of having to write all that gooey code - but if you insist on using low-level ADO.NET, that's about as good as it gets.
I would recomend you to use SqlDataAdapter and DataTable. In this you don't need to Open and Close connection explicitly.
Also in your current approach you are getting data in SqlDatareader and than loading in DataTable so you are creating an extra object which will occupy memory.
Using SqlDataAdadpter approach is called Disconnected or ConnectionLess while using SqlDataReader is called Connection Oriented approach.
Difference is that in ConnectinoOriented approach you need to Open and Close connection manually also connection should remain open until you are reading data. In other approach you can read data even connection is closed.
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
using(SqlCommand cmd = new SqlCommand("select * from testtable where id=#id", con));
{
adapter = new SqlDataAdapter(cmd);
cmd.Parameters.AddWithValue("#id", 1);
adapter.Fill(dt);
}
}
Is this new method that much better from an efficient perspective?
I don't think so. As far as I see, only difference between your methods is using of using statement and this method does not make your method more efficient. It provides an auto mechanism disposing for IDisposable objects.
Where should the sqlConn.Open() be placed in the code?
Just before when you need an open connection. In your fist case, I would use it just before SqlDataReader sqlDr = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection) line since I only need first time to an open connection.
Do I still need the CommandBehavior.CloseConnection in the
SqlDataReader now that its wrapped with a using?
It is still a better approach to use it. For example, if your code throws an exception on it and if you don't use CloseConnection, your code won't access the contents of your reader. Also, using CloseConnection may harm your code little bit based on this thread.
Any better way to do this, efficiently?
That depends a lot of things but if you use them in small project, ADO.NET will be efficient as well but I generally use EF as much as I can.
First of all, as I read in ur description, that u hammer in requests. So I assume u talk about alot of frequent requests. If this occurs, i highly recommend to not close ur sql connection after each query. This will speed up ur method actually a lot, because ur application doesn't need to communicate, handshake, and ... for every single query.
Is this new method that much better from an efficient perspective?
Using is actually nothing to do with performance. It's actually a helper for the developer, and to keep the Garbage Collection cleaner. Using does nothing else then calling the Object.Dispose() as using needs an IDisposable Object to work. So u don't have to deal with closing and disposing the connection. So performance grant equals to zero.
Where should the sqlConn.Open() be placed in the code?
If u keep in mind my first answer, u should establish the connection somewhere in the loading of ur window.
Do I still need the CommandBehavior.CloseConnection in the SqlDataReader now that its wrapped with a using?
No. If ur interested in what is using doing MSDN
Any better way to do this, efficiently?
See my first post. The rest of the actual query can't be boosted, because it's actually just building the query, and sending it to the server and finally retreiving it.
Ok, I'm settling for this solution:
try
{
using (SqlConnection sqlConn = new SqlConnection(Config.ConnStr))
using (SqlCommand sqlCmd = new SqlCommand("spr_Web_Content", sqlConn))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.Add("#Op", SqlDbType.VarChar, 100).Value = "SelectAllForNavigation";
sqlConn.Open();
using (SqlDataReader sqlDr = sqlCmd.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(sqlDr);
return dt;
}
}
}
catch (Exception)
{
return null;
}
It seems to provide the best performance and efficiency. I just have a couple more doubts before I wrap this topic and move on;
Do I save memory be returning a DataRow as opposed to a DataTable with 1 row?
I keep seeing using (var sqlConn = ... is this same as using (SqlConnection sqlConn = ...?
Thanks.
I have my main form which has a datagrid view connected to a database. Then I have a button that opens a separate form and I've got a few buttons etc on that secondary form.
I need to query the database from the secondary form but I'm not sure how to do that without creating a whole new connection, which I don't think I need since the program is already connected to the database. I'm just not sure how to reference the oleDB connection I made in that first form (I didn't code it in, I used the little arrow on the datagridview to connect it to the database using visual studio)
Now instead of creating that new connection, how do I reference the first connection made in the primary form?
Here is my code:
//parameterized update query
string updateCommandString = "UPDATE RoomsTable SET [Date Checked]=#checkedDate WHERE ID = #id";
using (OleDbConnection conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\users\spreston\documents\visual studio 2012\Projects\roomChecksProgram\roomChecksProgram\roomsBase.accdb"))
{
using (OleDbCommand updateCommand = new OleDbCommand())
{
OleDbTransaction transaction = null;
updateCommand.Connection = conn;
updateCommand.Transaction = transaction;
updateCommand.CommandText = updateCommandString;
updateCommand.CommandType = CommandType.Text;
updateCommand.Parameters.AddWithValue("#checkedDate", this.dateTimePicker1.Value.ToShortDateString());
updateCommand.Parameters.AddWithValue("#id", row.roomID);
try
{
conn.Open();
transaction = conn.BeginTransaction();
updateCommand.Transaction = transaction;
updateCommand.ExecuteNonQuery();
transaction.Commit();
conn.Close();
conn.Dispose();
}
catch(OleDbException ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
From a design standpoint, you should consider making a data access layer for your forms to utilize. You can create methods to retrieve those Db results for you so you consolidate that code and separate it from your form functionality. It may be just a small project, but it's good practice and if it's a project you want to grow, you'll want it laid out to be extendable.
Something like
class SomethingDA {
static DataTable GetMyStuff(your params) {
// establish connection, get your results
}
}
You can then call SomethingDa.GetMyStuff() to get what you need.
If you are Using the "Using" statement, your connection is closed after this code is run. You don't in fact need the conn.Close() and conn.Dispose() statements. Using does that for you.
Your best bet is to open up the connection again. It is generally a good practice to open and close connections as quickly as possible, although likely less important if your Access DB local. This generally does not impact performance too much as the OLE DB driver behind the scene will pool the connection and keep it open for a period of time.
Basically, I would like a brief explanation of how I can access a SQL database in C# code. I gather that a connection and a command is required, but what's going on? I guess what I'm asking is for someone to de-mystify the process a bit. Thanks.
For clarity, in my case I'm doing web apps, e-commerce stuff. It's all ASP.NET, C#, and SQL databases.
I'm going to go ahead and close this thread. It's a little to general and I am going to post some more pointed and tutorial-esque questions and answers on the subject.
MSDN has a pretty good writeup here:
http://msdn.microsoft.com/en-us/library/s7ee2dwt(VS.71).aspx
You should take a look at the data-reader for simple select-statements. Sample from the MSDN page:
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
It basicly first creates a SqlConnection object and then creates the SqlCommand-object that holds the actual select you are going to do, and a reference to the connection we just created. Then it opens the connection and on the next line, executes your statements and returns a SqlDataReader object.
In the while-loop it then outputs the values from the first row in the reader. Every time "reader.Read()" is called the reader will contain a new row.
Then the reader is then closed, and because we are exiting the "using"-secret, the connection is also closed.
EDIT: If you are looking for info on selecting/updating data in ASP.NET, 4GuysFromRolla has a very nice Multipart Series on ASP.NET 2.0's Data Source Controls
EDIT2: As others have pointed out, if you are using a newer version of .NET i would recommend looking into LINQ. An introduction, samples and writeup can be found on this MSDN page.
The old ADO.Net (sqlConnection, etc.) is a dinosaur with the advent of LINQ. LINQ requires .Net 3.5, but is backwards compatible with all .Net 2.0+ and Visual Studio 2005, etc.
To start with linq is ridiculously easy.
Add a new item to your project, a linq-to-sql file, this will be placed in your App_Code folder (for this example, we'll call it example.dbml)
from your server explorer, drag a table from your database into the dbml (the table will be named items in this example)
save the dbml file
You now have built a few classes. You built the exampleDataContext class, which is your linq initializer, and you built the item class which is a class for objects in the items table. This is all done automatically and you don't need to worry about it. Now say I want to get record with the itemID of 3, this is all I need to do:
exampleDataContext db = new exampleDataContext(); // initializes your linq-to-sql
item item_I_want = (from i in db.items where i.itemID == 3 select i).First(); // using the 'item' class your dbml made
And that's all it takes. Now you have a new item named item_I_want... now, if you want some information from the item you just call it like this:
int intID = item_I_want.itemID;
string itemName = item_I_want.name;
Linq is very simple to use! And this is just the tip of the iceberg.
No need to learn antiquated ADO when you have a more powerful, easier tool at your disposal :)
Reads like a beginner question. That calls for beginner video demos.
http://www.asp.net/learn/data-videos/
They are ASP.NET focused, but pay attention to the database aspects.
topics to look at:
ADO.NET basics
LINQ to SQL
Managed database providers
If it is a web application here are some good resources for getting started with data access in .NET:
http://weblogs.asp.net/scottgu/archive/2007/04/14/working-with-data-in-asp-net-2-0.aspx
To connect/perform operations on an SQL server db:
using System.Data;
using System.Data.SqlClient;
string connString = "Data Source=...";
SqlConnection conn = new SqlConnection(connString); // you can also use ConnectionStringBuilder
connection.Open();
string sql = "..."; // your SQL query
SqlCommand command = new SqlCommand(sql, conn);
// if you're interested in reading from a database use one of the following methods
// method 1
SqlDataReader reader = command.ExecuteReader();
while (reader.Read()) {
object someValue = reader.GetValue(0); // GetValue takes one parameter -- the column index
}
// make sure you close the reader when you're done
reader.Close();
// method 2
DataTable table;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(table);
// then work with the table as you would normally
// when you're done
connection.Close();
Most other database servers like MySQL and PostgreSQL have similar interfaces for connection and manipulation.
If what you are looking for is an easy to follow tutorial, then you should head over to the www.ASP.net website.
Here is a link to the starter video page: http://www.asp.net/learn/videos/video-49.aspx
Here is the video if you want to download it: video download
and here is a link to the C# project from the video: download project
Good luck.
I would also recommend using DataSets. They are really easy to use, just few mouse clicks, without writing any code and good enough for small apps.
If you have Visual Studio 2008 I would recommend skipping ADO.NET and leaping right in to LINQ to SQL
#J D OConal is basically right, but you need to make sure that you dispose of your connections:
string connString = "Data Source=...";
string sql = "..."; // your SQL query
//this using block
using( SqlConnection conn = new SqlConnection(connString) )
using( SqlCommand command = new SqlCommand(sql, conn) )
{
connection.Open();
// if you're interested in reading from a database use one of the following methods
// method 1
SqlDataReader reader = command.ExecuteReader();
while (reader.Read()) {
object someValue = reader.GetValue(0); // GetValue takes one parameter -- the column index
}
// make sure you close the reader when you're done
reader.Close();
// method 2
DataTable table;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(table);
// then work with the table as you would normally
// when you're done
connection.Close();
}
I'm basically trying to figure out the simplest way to perform your basic insert operation in C#.NET using the SqlClient namespace.
I'm using SqlConnection for my db link, I've already had success executing some reads, and I want to know the simplest way to insert data. I'm finding what seem to be pretty verbose methods when I google.
using (var conn = new SqlConnection(yourConnectionString))
{
var cmd = new SqlCommand("insert into Foo values (#bar)", conn);
cmd.Parameters.AddWithValue("#bar", 17);
conn.Open();
cmd.ExecuteNonQuery();
}
Since you seem to be just getting started with this now is the best time to familiarize yourself with the concept of a Data Access Layer (obligatory wikipedia link). It will be very helpful for you down the road when you're apps have more interaction with the database throughout and you want to minimize code duplication. Also makes for more consistent behavior, making testing and tons of other things easier.
using (SqlConnection myConnection new SqlConnection("Your connection string"))
{
SqlCommand myCommand = new SqlCommand("INSERT INTO ... VALUES ...", myConnection);
myConnection.Open();
myCommand.ExecuteNonQuery();
}