Beginner:
Hi Guys - looking for some help to see how should i open and close database connections.
Problem i am trying to resolve:
I have a set of stored procedures which needs to be executed in the data access layer.
My service call the DA method Get(Request req) as:
public Data Get(Request request)
{
var data = new Data();
data = GetData();
data.AppleData = GetGrapeData();
data.OrangeData = GetGrapeData();
data.GrapeData = GetGrapeData();
return data;
}
where all the getmethods getdata, getgrapedata etc are private methods in the Data access class and different SP's are called in each methods.
Now in each method i am opening and closing the database connection as:
{ try{
using (var connection = new SqlConnection(connectionString)
using (var command = connection.CreateCommand())
{
connection.open();
ExecuteSP();
connection.Close();
}
}catch()
{
}
}
Now
Is there any way i can do this so i have to open/ close the connection just once?
I am doing try catch in each private method. is that ok?
Is there any issue in the way i am doing it above?
Yes, you can open the connection just once. You could use a class or something to manage this, but that seems overkill to me for a simple scenario.
public Data Get(Request request)
{
using (var connection = new SqlConnection(connectionString))
{
try
{
connection.open();
var data = new Data();
data = GetData(connection);
data.AppleData = GetGrapeData(connection);
data.OrangeData = GetGrapeData(connection);
data.GrapeData = GetGrapeData(connection);
return data;
}
finally
{
connection.close()
}
}
}
And then in the methods that call the stored procedure:
private Date GetDate(SqlConnection connection)
{
using (var command = connection.CreateCommand())
{
return ExecuteSP();
}
}
You can put exception handling wherever you'd like, but if you aren't going to do anything with the exception, then you absolutely should not catch it.
With SQL Server, you don't want to leave connections open any longer than you need to. Other parts of the system, or another system, can be waiting for them.
And second on the ORM - either EF or NHibernate does this much better than most programmers.
So, to support the example I mentioned in my comment above, you could do something like this:
// This is your main class.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void SomeMethod(object sender, EventArgs e)
{
ConnectToSql connToSql = new ConnectToSql(); // Instantiate the new class here.
connToSql.SqlConnection(); // Use the new class
}
}
}
// This is the class that manages your SqlCommand and connection objects
namespace WindowsFormsApplication1
{
class ConnectToSql
{
public void SqlConnection()
{
try
{
string strConn = "Some connection string here.";
string strCmd = "Some Sql query string here.";
// Create your connection object.
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
// Create your command object and pass it the connection.
using (SqlCommand sqlCommand = new SqlCommand(strCmd, sqlConn))
{
sqlConn.Open();
// Do some work here.
sqlConn.Close();
}
}
}
catch (SqlException sqlExc)
{
throw;
}
catch (Exception exc)
{
throw;
}
}
}
A few things to note here:
This isn't the best approach. As was mentioned in comments, an ORM may be a better fit.
Each time you need to open the connection, you will need to use the new class so, it's best to instantiate it at the top-level of your class.
The using keyword will manage your connection and command objects for you since they both implement IDisposable.
Related
I want to create a class that has SQL connection and functions (like insert, select, delete queries) and I want to call it to my forms (buttons and etc.)
I don't know if it's possible or not or maybe there are some ways on doing this so...
I've done some research and come up with this code on class SQL connection and I'm not sure if it's correct.
Thank you very much in advance. I'm a beginner and want to learn more on c#.
Any type of response is appreciated. Thank you
Sorry for my bad English
using System.Data.SqlClient;
class SqlConnClass
{
public static SqlConnection GetConnection()
{
string str = "Data Source=localhost;Initial Catalog=kwem;Integrated Security=True;";
SqlConnection conn = new SqlConnection(str);
conn.Open();
return conn;
}
You were close! You may want to take the `conn.Open()' out of your method as you can open it for your query. (Remember to close it or put it in a using statement!)
public static void UpdateDB(string valToUpdate)
{
SQLConnection conn = GetConnection();
using (conn)
{
SQLCommand updateCommand = new SQLCommand(GetConnection(), "Update Table
Set Val = #newValue");
updateCommand.Parameters.AddWithValue("#newValue", valToUpdate);
conn.Open();
updateCommand.ExecuteNonQuery();
}
}
You would then do the same for any other kind of DB functions.
It's true but; if your string str do not work. Please try this:
string str = "Data Source=local host ;Initial Catalog=kwem;Integrated Security=True"
also you need to define sql table and then select your database.
You are on the right path.
What you are referring to is called a data access layer, or DAL for short.
It's a part of the n-tier architecture model (in the simple version there are 3 tiers - presentation, business logic and data access layer).
The basic concept is that you separate the presentation, logic and data into 3 different parts of the application.
As for the data access layer, usually you'll have a static or singleton class responsible to connect the business layer to the data. This class will contain methods for CRUD operations - Create, Read, Update and Delete data. You will need to create methods for each operation and for each data entity.
One approach I see all the time is this:
public static class DAL
{
private static string _ConnectionString = null;
static DAL() // A static constructor to initialize the connection string
{
_ConnectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
}
public static DataSet GetCategories()
{
var ds = new DataSet();
var sql = "SELECT * FROM Categories";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(ds);
}
}
}
return ds;
}
public static int DeleteCategory(int categoryId)
{
int rowsEffected = 0;
var sql = "DELETE FROM Categories WHERE Id = #Id";
using (var con = new SqlConnection(_ConnectionString))
{
using (var cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add("#Id", SqlDbType.Int).Value = categoryId;
con.Open();
cmd.ExecuteNonQuery();
}
}
return rowsEffected;
}
}
and so on. As you can see, there is a lot of code that repeats itself.
This means longer code, herder maintenance, and if for some reason you will want to support other types of databases (like migrating to MySql, Oracle or whatever) You will have to work very hard to change all the vendor specific classes in your DAL (SqlConnection, SqlCommand etc`).
These problems are exactly the reason I wrote ADONETHelper. I've been using it for a few years (mostly in earlier, different forms) and I feel now it's matured enough to go public. It's currently under MIT licence, meaning it's completely free and you can download your copy and change it as you see fit.
Should you choose to use it, your DAL class should probably look like this:
public static class DAL
{
private static IDBHelper _DB;
static DAL() // A static constructor to initialize _DB
{
// initialize connection string from config file
var connectionstring = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
_DB = DBHelperFactory.GetInstance(DataBaseType.SQLServer, connectionstring);
}
public static DataSet GetCategories()
{
var sql = "SELECT * FROM Categories";
return _DB.FillDataSet(sql, CommandType.Text);
}
public static int DeleteCategory(int categoryId)
{
var sql = "DELETE FROM Categories WHERE Id = #Id";
var param = _DB.CreateParameter("#Id", ADONETType.Int, categoryId);
return _DB.ExecuteNonQuery(sql, CommandType.Text, param);
}
}
As you can see, code repetitions are down to the bare minimum, and migrating to a different database is as simple as changing the static constructor to use a different DataBaseType. Of course, if you are using vendor-specific sql you will have to change that too.
this is a piece of code which is showing exception. It take sql query entered in text from textbox on the Window form (testform) and display the result in excel sheet. how can i take value in string to so that it dont show exception and that sql1 is textbox name is empty function in Testform.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.IO;
using System.Windows.Forms;
using Exceloutput_Application;
public class ProcessDataset
{
public ProcessDataset()
{
}
public static DataTable ReadTable()
{
TestForm t = new TestForm();
var returnValue = new DataTable();
var conn = new SqlConnection(ConnectionString._connectionString);
string st = t.sql1.Text;
try
{
conn.Open();
var command = new SqlCommand(st, conn);
using (var adapter = new SqlDataAdapter(command))
{
adapter.Fill(returnValue);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
finally
{
if (conn.State == ConnectionState.Open)
conn.Close();
}
return returnValue;
}
}
You either assume that instantiating (new) a Form magically shows it or gets a reference to an existing open form. None of those assumptions is true.
To show a form to the user you either call Application.Run for your first form (the main form of your application) or Show
or ShowDialog on a instance you created.
Let me add comments to the first few lines of your ReadTable method:
TestForm t = new TestForm(); // this ONLY creates a NEW form in memory
// if you were looking at a TestForm already t holds a new form
// and not the one you're looking at.
var returnValue = new DataTable();
var conn = new SqlConnection(ConnectionString._connectionString);
// the form is not shown to the user at this point
// and never will be because YOU didn't tell it to Show
// The textbox is empty
string st = t.sql1.Text;
// st will be an empty string here
With that explained let's see possible solutions. You might be tempted to add
t.Show();
directly after you created the TestForm. That does show the form but Show is non-blocking. Which means it will continue immediately with the rest of the code still leading to an empty result in st.
t.ShowDialog();
will enable you to see the form and fill in any values. ShowDialog will block until the users closes the form or you have a button that calls Close or Hide in the click event.
Based on the sparse information you provided I assume you already have TestForm open, with a button on it that calls ReadTable. If you change ReadTable to accept a the sql string, you don't have to juggle with the forms.
Something like this will do:
public class ProcessDataset
{
// Takes a Sql string
public static DataTable ReadTable(string sql)
{
var returnValue = new DataTable();
// checks if there is a sql string provided
if (!String.IsNullOrEmpty(sql))
{
var conn = new SqlConnection(ConnectionString._connectionString);
conn.Open();
var command = new SqlCommand(sql, conn);
// rest of code
}
else
{
// show message to user
MessageBox.Show(" no sql command ");
}
return returnValue;
}
}
And you will call it from your click event like so:
private void button2_Click(object sender, EventArgs e)
{
var resultset = ProcessDataset.ReadTable(sql1.Text);
}
tl;dr There is not much wrong with your SqlCommand code. You simply failed in getting the correct reference to your Textbox that contains some sql statement. Calling sqlcommand with an empty string raises the exception you are seeing.
I'm a real noob in .NET and i'm trying to link a simple command line application (in C#) with a SQL server database. I'm now able to connect the program with the database but not to recover the data that are in it. Here is my code :
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
string connectionString = GetConnectionString();
string queryString = "SELECT USER_ID FROM dbo.ISALLOCATEDTO;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = queryString;
try
{
connection.Open();
SqlDataReader reader = command.ExecuteReader();
int i = 0;
while (reader.Read())
{
i++;
Console.WriteLine("Field "+i);
Console.WriteLine("\t{0}",reader[0]);
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
//Console.WriteLine("Hello world");
string x = Console.ReadLine();
}
static private string GetConnectionString()
{
return "Data Source=FR401388\\SQLEXPRESS;Initial Catalog=Test;";
+ "Integrated Security=SSPI";
}
}
}
But when i'm running it and even if my table is not empty (I've seen it in the sql server studio), I cannot recover the data by using the read() method.
What I've done so far : try to change the name of the datatable with a fake one : the datatable is not found (so the link between sql server database and programm seems to be valid).
I'm using Windows Authentication in sql server, dunno if it's changing anything... (Once again : i'm very new to all of that).
Thanks !
Your code should work.
A possible cause is: You are looking at a different database.
This is quite common if you use Server Explorer inside VS with a connectionstring different from the one used in code.
Create sqlserver connection in class
call connection class to use all form.
I want to create SQLServer connection in class with C# to use all forms.
Hereabout code of connection in class file
public System.Data.SqlClient.SqlConnection Con = new System.Data.SqlClient.SqlConnection();
public System.Data.SqlClient.SqlCommand Com = new System.Data.SqlClient.SqlCommand();
public string conStr;
public SQL2(string conStr)
{
try
{
Con.ConnectionString = conStr;
Con.Open();
Com.Connection = Con;
Com.CommandTimeout = 3600;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public bool IsConnection()
{
Boolean st;
if (Con.State==ConnectionState.Open)
{
st=true;
}
else
{
st = false;
}
return st;
}
Can give me full example code?
What you probably want is a factory that you use to use to create a connection:
using(var connection = databaseConenctionFactory.Create())
{
// then do want you want here
}
As LarsTech mentioned you don't want to keep open connections. Open/Use/Close. The using syntax is rather useful here as it takes care of all the unnecessary fluff. So once you are in a habit of using using you will not run into any weird behaviour in production systems.
There is quite a bit around implementing something like this so you could do some research. You could make use of the ADO Provider Factories and use IDbConnection instead of a specific implementation to abstract you implemetation.
You could also usse dependency injection to get to you factory/factories.
So choose your poison :)
I'm a big fan of keeping my code simple and trim so it can be re-usable, on thing i'm struggling with is using the data reader for different types of objects, I had it in a method and found there were problems with connections closed or being left open. SO I am being forced, for the mean time to copy and paste the code, which is something I hate!!!
Is there any way I can scale this down so I can put it in a method and make it re-usable and nice?
ENT_AuctionBid ret = new ENT_AuctionBid();
try
{
SqlParameter[] Params = new SqlParameter[]{
new SqlParameter("#ID", ID )
};
using (SqlConnection conn = new SqlConnection(this.ConnectionString))
{
using (SqlCommand command = new SqlCommand("GetItem", conn))
{
SqlDataReader reader;
command.CommandType = CommandType.StoredProcedure;
conn.Open();
command.Parameters.AddRange(Params);
reader = command.ExecuteReader(CommandBehavior.SingleRow);
while (reader.HasRows)
{
while (reader.Read())
{
//
ret = this.Convert(reader);
}
reader.NextResult();
}
reader.Close();
}
}
}
catch (Exception ex)
{
}
return ret;
You should use SQLDataAdapter.
Here's a nice example on how to use it:
http://www.dotnetperls.com/sqldataadapter
Also, you might want to consider switching to Entity Framework, it will make your data access much, much easier, but might be complicated in an existing project.
You can make it using a lot less lines:
// Skipped creating temp variable
try {
using (SqlConnection conn = new SqlConnection(this.ConnectionString))
using (SqlCommand command = new SqlCommand("GetItem", conn) { CommandType = CommandType.StoredProcedure} ) {
command.Parameters.AddWithValue(#ID, ID);
conn.Open();
// reader is IDisposable, you can use using
using (var reader = command.ExecuteReader(CommandBehavior.SingleRow)) {
// Skipped parsing multiple result sets, you return after the first
// otherwise there's no point using SingleRow
// If nothing is read, return default value
return reader.Read() ? this.Convert(reader) : new ENT_AuctionBid();
}
}
}
catch (Exception ex) {
// Handle your exception here
}
// Return default value for error
return new ENT_AuctionBid();
All connections are closed using this code (because using is used). No unneeded loops are created, becuase you only expect a single row. And the temporary variable is not needed, so the abondend object is not created, only when it is used it is created.
This is a bit smaller:-
try
{
using (SqlConnection conn = new SqlConnection(this.ConnectionString))
{
using (SqlCommand command = new SqlCommand("GetItem", conn))
{
command.Paramaters.AddWithValue("#ID",ID);
command.CommandType = CommandType.StoredProcedure;
conn.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
//
ret = this.Convert(reader);
}
}
}
}
catch (Exception ex)
{
}
Create helper methods for creating and returning an object of type SqlCommand. Pass a connection object to this helper method as well as stored procedure name and parameters list (if any). If you have different objects that are created from the data reader, pass the data reader to a constructor and let it generate an object based on that data.
As for closing the connection you should always have try...catch...finally. In the finally section close the connection.
In my projects i usually solve this problem creating an utility class that contains all the methods to access to the DB and manage inside all the stuff related to the db connection and the adapter.
For example a class called DBSql which contains a connection (SqlConnection connection;) as private member and the following methods:
//execute the query passed to the function
public System.Data.DataSet ExecuteQuery(string query)
//returns if a query returns rows or not
public bool HasRows(string query)
//execute commands like update/insert/etc...
public int ExcuteNonQuery(string sql)
In my class, you just pass a string and the class initialize the various DataAdapter and Command to execute it and return a dataset. Obiously you can complicate it to manage parameters/transaction and everything else.
In this way you are sure that the connection and the object are always handled the same way, and, hopefully, in a correct way.
You can use a utility file, such as SqlHelper.cs from Microsoft Data Access Application Block. Then all the code you need is this:
using (SqlDataReader sdr = SqlHelper.ExecuteReader(this.ConnectionString, "GetItem", ID))
{
while (sdr.Read())
{
ret = this .Convert(sdr);
}
}
You could start using LINQ-to-SQL, which has it's own DataClass system in which you just drag-&-drop your database tables and stored procedures. Then you just have to create an instance at the top of your classes -- private MyCustomDataClass _db = new MyCustomDataClass(); and then you can just type in _db.<Here all datatables and SPROCs will appaer for you to choose>.
Example (from when all SPROCs are added to the DataClass)
private MyCustomDataClass _db = new MyCustomDataClass();
public void MethodToRunSPROC(string email, Guid userId)
{
_db.MySPORC_AddEmailToUser(email, userId);
}