I just want an opinion on the proper usage or a proper design with regards to using SqlConnection object. Which of the 2 below is the best use:
A data provider class whose methods (each of them) contain SqlConnection object (and disposed when done). Like:
IList<Employee> GetAllEmployees()
{
using (SqlConnection connection = new SqlConnection(this.connectionString)) {
// Code goes here...
}
}
Employee GetEmployee(int id)
{
using (SqlConnection connection = new SqlConnection(this.connectionString)) {
// Code goes here...
}
}
or
SqlConnection connection; // initialized in constructor
IList<Employee> GetAllEmployees()
{
this.TryOpenConnection(); // tries to open member SqlConnection instance
// Code goes here...
this.CloseConnection();
// return
}
Employee GetEmployee(int id)
{
this.TryOpenConnection(); // tries to open member SqlConnection instance
// Code goes here...
this.CloseConnection();
// return
}
Or is there a better approach than this? I have a focused web crawler type of application and this application will crawl 50 or more websites simultaneously (multithreaded) with each website contained in a crawler object and each crawler object has an instance of a data provider class (above).
The actual database connections will be pooled. As long as all of your SqlConnection instances use the same connection string, they'll all really use the same connection.
I find it cleaner to create the connection instance, use it, then dispose it (in a using block). That way, if the code needs to change to use a different connection string, to use a transaction, or whatever, you have all you need to make the change available right there.
Maybe not really related, but the only time I'd separate any connection object to the class instance level is when I want to create a clear separation of concern to what each method is doing... Perhaps it's too long and need to be refactored into several pieces and each of them need to operate on the same connection as part of a transaction.
I.e.
Create a connection
Start transaction
Call a subroutine to update an order header (passing along the connection or get it from the instance)
Call a subroutine to update all order details (passing along the conneciton or get it from the instance)
End transaction
Close connection
Otherwise, I'd pretty much stick to option 1. W/ connection pooling it's basically won't cost you anything.
Related
I have been struggling with this bit for over a day now. It appears that many people have asked about similar thing, but they usually want to do something way more advance than what I need. I got an idea what it should look like (I think), but struggle with actually properly implementing it - so here it goes:
I have a form application that does some Odbc, Sql, Csv import/exports.
My main class is the ImportForm class, which contains all the buttons, controls it also creates SQL and ODBC connections in each constructor etc.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ImportForm importForm = new ImportForm();
Application.Run(importForm);
}
.
public partial class ImportForm : Form
public static SqlConnection sqlConnection = new SqlConnection(ConstantValues.SqlConnectionString);
public static OdbcConnection odbcConnection = new OdbcConnection(ConstantValues.OdbcConnectionString);
(...)
I now have few other classes that do different things. For instance once of imports CSV files into SQL Server. It does it through SqlBulk based on the SQL connection defined in the ImportForm class:
internal class CsvImportIntoSql
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
This, however, returns a syntax error 'The name does not exist in the current context'
I tried:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(importForm.sqlConnection);
But it doesnt work, the class ImportForm is available in the context, but its defined instance importForm is not and I cannot understand why and what I should do to make it work - I have been struggling with that for a while and have to employ different workarounds which often do not make for good code.
Any help would be appreciated.
Almost right: you need the class name ImportForm, not an instance of it ( importForm) to access a static property:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(ImportForm.sqlConnection);
If the CsvImportIntoSql instance is created in the ImportForm, then your best option would be to inject the sqlConnection, or if it is likely to change after the CsvImportIntoSql instance is created then inject a refrence to the CsvImportIntoSql instance itself.
If I understand, you are trying to use the same sqlConnection variable that is defined in another class. but it appears that you have declared this variable as static, which should help while referring to it from another class:
Try to replace
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(sqlConnection);
with:
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(ImportForm.sqlConnection);
This should work. however,using the same connection in multiple instance is not always a good practice. instead, you can initialize a new connection for each job.
Here is my sample code:
public static class MySqlHelper
{
private static string constring = ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString;
public static int ExecuteNonQuery(string mysqlquery)
{
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(mysqlquery, conn);
int result;
try
{
conn.Open();
result= cmd.ExecuteNonQuery();
}
finally
{
conn.Close();
}
return result;
}
}
Usage: MySqlHelper.ExecuteNonQuery("select * from customers");
I would like to know the issues using this static class.
I can change my class as mentioned here but I have been using this class in couple of websites and I will need couple days to change it in every place and test it out.
Thanks for any inputs.
Edit: Updated the code. Does that make difference on the answers provided? Sorry, I should have posted in the beginning.
I am assuming the connection string doesnt change during execution (you might want to make it readonly). Since there is no other shared state shown in the question, there are no real problems.
However, if you have any shared state you have a huge threading problem. And if you have shared connections you have an even bigger problem.
But as written, with no significant static fields: no problem.
I thought he was pretty clear on his answer.
Writing my own Provider Class in ASP.NET
"remember that the connection will be shared at the same instance for all users, which can cause bad problems..."
Static classes are difficult to test.
Your question mentions that for a change you'll have to change the class on a couple websites. If your websites were coupled to an interface, then swapping out the implementation would be relatively simple.
In my own projects I avoid public static classes. They can get unwieldy very quickly.
As such no issue it depends how you are using this class, ideally it part of abstract factory pattern to have static connections so that same connection can be used all over application, but having methods such as executereader and other mthods is not a good choice. similarly always check that connection has not been closed or its state before its usage, because if you are having static connection and you used using syntax with executereader then it will close the connection and if some other method used connection after this then it will get the error
The obvious drawbacks are:
hardcoded connection string
without connection pooling in the driver this is very bad: //open conn + //close conn
1) can be ugly solved by using a singleton as the connection string name
2) cannot be solved in a static class without introducing shared data: ie. without planting a knife in your back.
Do you know that the MySQL Connector for .NET now has a MySqlHelper class (you can check it in the source here)?
If you are going to take this route you many want to consider using the Microsoft DAAB SqlHelper v2 offering. It uses the same concept but is much more robust. It also caches SqlParameters. The code came out circa 2001 and has been in constant use by many developers.
http://www.microsoft.com/download/en/details.aspx?id=435
I have a web service that is quite heavy on database access. It works fine in test, but as soon as I put it in production and ramp up the load it starts churning out errors that are raised when something calls a method in the DataContext. The error is normally one of these:
Object reference not set to an instance of an object
Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'.
but not always.
Any single web service requests can result as many as 10 or 15 database queries, and 1 or 2 updates.
I've designed my application with a data access layer which is a bunch of objects that represent the tables in my database which hold all the business logic. The is a separate project to my web service as it's shared with a Web GUI.
The data access objects derive from a base class which has a GetDataContext() method to initiate an instance of the data context whenever it's needed.
All throughout my data access objects I've written this:
using (db = GetDataContext())
{
// do some stuff
}
which happily creates/uses/disposes my DataContext (created by sqlmetal.exe) object for each and every database interaction.
After many hours of head scratching, I think I've decided that the cause of my errors is that under load the datacontext object is being created and disposed way too much, and I need to change things to share the same datacontext for the duration of the web service request.
I found this article on the internet which has a DataContextFactory that seems to do exactly what I need.
However, now that I've implemented this, and the DataContext is saved as an item in the HttpContext, I get...
Cannot access a disposed object.
Object name: 'DataContext accessed after Dispose.'
...whenever my datacontext is used more than once. This is because my using (...) {} code is disposing my datacontext after its first use.
So, my question is... before I go through my entire data access layer and remove loads of usings, what is the correct way to do this? I don't want to cause a memory leak by taking out the usings, but at the same time I want to share my datacontext across different data access objects.
Should I just remove the usings, and manually call the dispose method just before I return from the web service request? If so then how go I make sure I capture everything bearing in mind I have several try-catch blocks that could get messy.
Is there another better way to do this? Should I just forget about disposing and hope everything is implicitly cleaned up?
UPDATE
The problem doesn't appear to be a performance issue... requests are handled very quickly, no more than about 200ms. In fact I have load tested it by generating lots of fake requests with no problems.
As far as I can see, it is load related for one of two reasons:
A high number of requests causes concurrent requests to affect each other
The problem happens more frequently simply because there are a lot of requests.
When the problem does occur, the application pool goes into a bad state, and requires a recycle to get it working again.
Although I would prefer the unit-of-work approach using using, sometimes it doesn't always fit into your design. Ideally you'd want to ensure that you are freeing up your SqlConnection when you're done with it so that anothe request has a chance of grabbing that connection from the pool. If that is not possible, what you would need is some assurance that the context is disposed of after each request. This could be done a couple of ways:
If you're using WebForms, you can tie the disposal of the DataContext at the end of the page lifecycle. Make a check to the HttpContext.Items collection to determine if the last page had a data context, and if so, dispose of it.
Create a dedicated IHttpModule which attaches an event to the end of the request, where you do the same as above.
The problem with both of the above solutions, is that if you are under heavy load, you'll find that a lot of requests hang about waiting for a connection to be made available, likely timing out. You'll have to weigh up the risks.
All in all, the unit-of-work approach would still be favoured, as you are releasing the resource as soon as it is no longer required.
I managed to fix this myself...
I had a base class that had a method that would create the DataContext instance, like this:
public abstract class MyBase {
protected static DataContext db = null;
protected static DataContext GetDataContext() {
return new DataContext("My Connection String");
}
// rest of class
}
And then, in the classes that inherited MyBase where I wanted to do my queries, I had statements like this:
using (db = GetDataContext()) { ... }
The thing is, I wanted to access the database from both static methods and non-static methods, and so in my base class, I'd declared the db variable as static... Big mistake!
If the DataContext variable is declared as static, during heavy loads when lots of things are happening at the same time the DataContext is shared among the requests, and if something happens on the DataContext at exactly the same time it screws up the instance of the DataContext, and the Database connection stored in the Application pool for all subsequent requested until it's recycled, and the database connection is refreshed.
So, the simple fix is to change this:
protected static DataContext db = null;
to this:
protected DataContext db = null;
...which will break all of the using statements in the static methods. But this can easily be fixed by declaring the DataContext variable in the using instead, like this:
using (DataContext db = GetDataContext()) { ... }
This happens if you have, for example, an object that references another object (i.e. a join between two tables) and you try to access the referenced object after the context has been disposed of. Something like this:
IEnumerable<Father> fathers;
using (var db = GetDataContext())
{
// Assume a Father as a field called Sons of type IEnumerable<Son>
fathers = db.Fathers.ToList();
}
foreach (var father in fathers)
{
// This will get the exception you got
Console.WriteLine(father.Sons.FirstOrDefault());
}
This can be avoided by forcing it to load all the referenced objects like this:
IEnumerable<Father> fathers;
using (var db = GetDataContext())
{
var options = new System.Data.Linq.DataLoadOptions();
options.LoadWith<Father>(f => f.Sons);
db.LoadOptions = options;
fathers = db.Fathers.ToList();
}
foreach (var father in fathers)
{
// This will no longer throw
Console.WriteLine(father.Sons.FirstOrDefault());
}
I created a C#.net app that uses dates from a SQL Server 2008 database table. Is there a way for me to temporarily store the data so that my program does not have to repeatedly make server calls for the same set of information? I know how to pull the info I need and create a temporary dataset, however, it is only accessible to the particular method or class and then goes away. I need the results to be universally available until the program closes.
This is what I have so far and I am not sure where to go next:
SqlConnection ReportConnect = new SqlConnection(ConnectionString);
String reportQuery = #"SELECT DISTINCT DATE FROM dbo.myTable ORDER BY DATE DESC";
ReportConnect.Open();
SqlCommand cmd = ReportConnect.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = ReportConnect;
cmd.CommandText = reportQuery.ToString();
SqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read()) {
//I can access the results here
}
//how do I add this data for the life of the program instance to my current
//dataset. Let's say the dataset is named "activeDataset"
If you are going to use key/value pair caching, I recommend you use HttpRuntime.Cache (available outside ASP.NET applications) since it already does alot of work for you.
In it's simplest implementation:
public IList<DateTime> GetUniqueDates()
{
const string CacheKey = "RepositoryName.UniqueDates";
Cache cache = HttpRuntime.Cache;
List<DateTime> result = cache.Get[CacheKey] as List<DateTime>;
if (result == null)
{
// If you're application has multithreaded access to data, you might want to
// put a double lock check in here
using (SqlConnection reportConnect = new SqlConnection(ConnectionString))
{
// ...
result = new List<DateTime>();
while(reader.Read())
{
result.Add((DateTime)reader["Value"]);
}
}
// You can specify various timeout options here
cache.Insert(CacheKey, result);
}
return result;
}
Having said that, I usually use IoC trickery to create a caching layer in front of my repository for the sake of cohesion.
You could create a singleton object, and store the data in this object.
Be aware that there is a lot more to single ton objects that you will have to think about.
Have a look at
Implementing the Singleton Pattern
in C#
Singleton pattern
Implementing Singleton in C#
You should use SQLCacheDependency. Take a look at MSDN
You could store the datatable in a static variable that would be accesible from any part of your code (is this necessary?).
public class MyDataSetCache
{
public static DataSet MyDataSet { get; set; }
}
Some other code...
// SQL Statements....
MyDataSetCache.MyDataSet = activeDataset // Editted to follow OP :-)
I usually serialize whole object to a file and try to read it first before going to database.
You can use a set of implementation hooks to achieve result:
Common data-application layer (data singleton or some data coupling using static class with lesser "visible" methods' dependencies)
Use caching -- you can use Dictionary and common string-keys to detect (ContainsKey method) whether data is already fetched or needs sql-server call. This can be useful when you need different DataSets. Dictionary works pretty fast.
You can definately use Cache to reduce database hits, Besides using SqlDependency you can have a cache based on time. You can invalidate your cache let's say every 4 hours,and hit the database again. Check out Cache.Insert()
I am looking to do something like this:
access records in db with a datareader. I won't know how many records will come back - somewhere between 1 and 300 most of the time. The data will look something like this "0023","Eric","Harvest Circle", "Boston" for each record.
I wanted to immediately populate something (array, list?) and close the connection.
Pass the filled object back to my webservice where I will convert it to JSON before sending on to client.
The problem I am running into is what object/objects to populate with data from the datareader. I started out using an ArrayList (and have now read about using List instead), but although I could get back all the records (in this case just 2 Items), I could not access the individual fields inside each Item (Eric, Boston, etc).
Enter Plan B: foreach record in datareader, add the individual column values to an array and then add each array to the List. I think this will work, but I am not sure how to instantiate an array when I don't know how many would need to be instantiated. In other words, I would normally do this string[] myarray = new string[]{"eric", "boston", "etc"};
But if I have multiple records, what does that look like? Populate array, add to List, clear original array and then repopulate it, add it to List, etc?
Any help would be greatly appreciated! Also, I am very open to alternative ways of doing this.
Thanks!
The standard answer here, short of using a persistence layer like the Entity Framework, is to create "entity" classes with the fields you need. Something like:
class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
... and then collect these up in a collection of some kind. A List<Customer> is fine.
List<Customer> customers = new List<Customer>();
string connectionString = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("GetData");
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Customer c = new Customer();
c.Id = (int)reader["ID"];
c.FirstName = (string)reader["FirstName"];
c.LastName = (string)reader["LastName"];
customers.Add(c);
}
}
}
If you have a large number of tables, or a mutable list of fields, this can get hard to maintain. For simple tasks, though, this works fine.
Odds are you don't need a concrete class like a List or array. An IEnumerable is probably good enough. With that in mind, this is my favorite pattern:
public IEnumerable<IDataRecord> GetData()
{
using (var cn = getOpenConnection(connectionString))
using (var cmd = new SqlCommand("GetData", cn))
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
You could also modify that to create strongly-typed business objects, but I generally keep that in a separate layer/tier. Iterator blocks will do lazy evaluation/deferred execution and so the extra translation tier will not require an additional iteration of the results.
There is one trick with this code. You need to be sure you copy the data in each record to a real object at some point. You can't bind directly to it, or you'll get potentially-surprising results. One variation I use more often is to make the method generic and require a Func<IDataRecord, T> argument to translate each record as it is read.
Michael's answer is usually your best bet. Once things start getting complicated, you can add abstractions (you'll need object factories that take in sql readers and various other fun things) and start passing around objects and factories. I've found this strategy is pretty helpful, and a well-written datalayer class can be used throughout your database-related projects.
One alternative is to use an SqlDataAdapter and to convert your output to a DataSet. In my experience this is pretty unwieldy and generally a pretty bad idea. That said, if your tendency is to grab a chunk of data, manipulate it (update pieces, add new pieces, delete pieces), this can be a nice way to do it in memory with C# code. Think twice before trying this technique. This is basically equivalent to grabbing data and populating a List of rows, though a DataSet has a bit more stuff in it than an array (e.g. it includes column names).
I feel like using an SqlDataAdapter to populate a DataSet is the closest answer to giving you what you are asking for in your question but the worst answer in terms of giving you what you actually need.
Create an object that has properties that matches the fields that will be coming back in the datareader:
public class MyClass
{
public int Id{get;set;}
public string Name{get;set;}
....
}
Then, foreach over all the results in the datareader. Then, create an object of this type and set all the properties with the values in the columns for that records. Then, add them to a List<MyClass>.
I would recommend looking into LINQ to SQL (if you have a very simple database), or NHibernate (if you have a more complex database). These are OR mappers that can greatly simplify the process of turning a SQL query into objects that can be used in your domain, passed through services, etc.
I think a simple solution is in order here. I would create a DataAdapter and then fill a DataTable with the data. You can then close the connection, and the data table will remain populated, since, unlike ADO, ADO.NET defaults to disconnected recordsets.
You can then easily access the data by fieldname, e.g.,
myDataTable["FirstName"].ToString()
If all you are going to do is convert the data to JSON, creating an object that maps properties to the database fields seems unnecessary since ADO.NET gives you this out of the box.