Best way to handle exception in ADO.Net repository pattern - c#

i have design small repository pattern for ado.net. now i could not manage to handle exception proper way. i want to push error to calling environment if any occur. if no error occur then result set will be push to calling environment.
i have repository called AdoRepository which extend other repository classes like employee etc. we are calling employee repository function from mvc controller. so i want to push error to mvc controller from employee repository if any occur during data fetch, if no error occur then data will be sent to mvc controller. here is my full code. please have look and share the idea for best design. if possible paste rectified code here.
Base repository
public abstract class AdoRepository<T> where T : class
{
private SqlConnection _connection;
public virtual void Status(bool IsError, string strErrMsg)
{
}
public AdoRepository(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
public virtual T PopulateRecord(SqlDataReader reader)
{
return null;
}
public virtual void GetDataCount(int count)
{
}
protected IEnumerable<T> GetRecords(SqlCommand command)
{
var reader = (SqlDataReader) null;
var list = new List<T>();
try
{
command.Connection = _connection;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
list.Add(PopulateRecord(reader));
}
reader.NextResult();
if (reader.HasRows)
{
while (reader.Read())
{
GetDataCount(Convert.ToInt32(reader["Count"].ToString()));
}
}
Status(false, "");
}
catch (Exception ex)
{
Status(true, ex.Message);
}
finally
{
// Always call Close when done reading.
reader.Close();
_connection.Close();
_connection.Dispose();
}
return list;
}
protected T GetRecord(SqlCommand command)
{
var reader = (SqlDataReader)null;
T record = null;
try
{
command.Connection = _connection;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
record = PopulateRecord(reader);
Status(false, "");
break;
}
}
catch (Exception ex)
{
Status(true, ex.Message);
}
finally
{
reader.Close();
_connection.Close();
_connection.Dispose();
}
return record;
}
protected IEnumerable<T> ExecuteStoredProc(SqlCommand command)
{
var reader = (SqlDataReader)null;
var list = new List<T>();
try
{
command.Connection = _connection;
command.CommandType = CommandType.StoredProcedure;
_connection.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
var record = PopulateRecord(reader);
if (record != null) list.Add(record);
}
}
finally
{
// Always call Close when done reading.
reader.Close();
_connection.Close();
_connection.Dispose();
}
return list;
}
}
StudentRepository which extend base AdoRepository
-----------------------------------------------
public class StudentRepository : AdoRepository<Student>
{
public int DataCounter { get; set; }
public bool hasError { get; set; }
public string ErrorMessage { get; set; }
public StudentRepository(string connectionString)
: base(connectionString)
{
}
public IEnumerable<Student> GetAll()
{
// DBAs across the country are having strokes
// over this next command!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents"))
{
return GetRecords(command);
}
}
public Student GetById(string id)
{
// PARAMETERIZED QUERIES!
using (var command = new SqlCommand("SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE Id = #id"))
{
command.Parameters.Add(new ObjectParameter("id", id));
return GetRecord(command);
}
}
public IEnumerable<Student> GetStudents(int StartIndex, int EndIndex, string sortCol, string sortOrder)
{
string strSQL = "SELECT * FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
strSQL += " ORDER BY " + sortCol + " " + sortOrder;
strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
var command = new SqlCommand(strSQL);
return GetRecords(command);
}
public override Student PopulateRecord(SqlDataReader reader)
{
return new Student
{
ID = Convert.ToInt32(reader["ID"].ToString()),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
IsActive = Convert.ToBoolean(reader["IsActive"]),
StateID = Convert.ToInt32(reader["StateID"].ToString()),
StateName = reader["StateName"].ToString(),
CityID = Convert.ToInt32(reader["CityID"].ToString()),
CityName = reader["CityName"].ToString()
};
}
public override void GetDataCount(int count)
{
DataCounter = count;
}
public override void Status(bool IsError, string strErrMsg)
{
hasError = IsError;
ErrorMessage = strErrMsg;
}
}
calling StudentRepository from mvc controller like below way
public class StudentController : Controller
{
private StudentRepository _data;
public StudentController()
{
_data = new StudentRepository(System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString);
}
// GET: Stuent
public ActionResult List(StudentListViewModel oSVm)
{
StudentListViewModel SVm = new StudentListViewModel();
SVm.SetUpParams(oSVm);
SVm.Students = _data.GetStudents(SVm.StartIndex, SVm.EndIndex, SVm.sort, oSVm.sortdir).ToList();
SVm.RowCount = _data.DataCounter;
return View("ListStudents",SVm);
}
}

I don't get the point of this:
catch (Exception ex)
{
Status(true, ex.Message);
}
Simply not catch the exception and let it bubble up to the caller who, according to you, will know to handle it. No callbacks necessary.
Storing retrieved data in instance state seems like a bad way to go. Rather, return an object with that data. That results in a more straight forward API and has less mutable state.
finally
{
reader.Close();
_connection.Close();
_connection.Dispose();
}
There is a better way to go about this: Wrap resources in a using statement. In particular, part ways with the superstitious double dispose pattern.

Let the caller deal with the exception making sure that you log a decent error message (showing all relevant fields). The Status class will annoy the hell out of support people as it swallows the stack trace and says nothing about the data which has caused the error. DB exceptions are often caused by malformed data so its important to have this data logged when things go wrong.
As an aside, your PopulateRecord and GetDataCount methods should be abstract as the base versions do nothing. Another dev could easily think they don't need to implement these methods and would be left with a class with useless PopulateRecord and GetDataCount methods.

Related

How to write a get method that can be used for all classes with MySqlConnection C#

I have methods to get data from database as below. The problem is if I have a number of classes, I need to write a number of get-data methods to retrieve the list of corresponding objects although the the logic is the same, only the classes, properties and table name are different.
I want to know if it is possible to write only 1 method to use for all classes. The challenge part is I don't know to how to cast the reader data to the data type of the properties.
I will pass in the object, the columns and the table name. For example:
// I want to write this method so it can be used for all classes
public List<Object> getData(string className, string[] columns, string tableName) {...}
public List<Client> GetClients()
{
List<Client> list = new List<Client>();
try
{
conn.Open();
string sql = "SELECT id, clientName, info, hidden from clients";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Client p = new Client((int)rdr[0], (string)rdr[1], (string)rdr[2], Convert.ToBoolean(rdr["hidden"]));
list.Add(p);
}
rdr.Close();
return list;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return null;
}
finally
{
conn.Close();
}
}
public List<RepPrefix> GetRepPrefixes()
{
List<RepPrefix> list = new List<RepPrefix>();
try
{
conn.Open();
string sql = "SELECT id, prefixName, hidden from repPrefix";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
RepPrefix p = new RepPrefix((int)rdr[0], (string)rdr[1], Convert.ToBoolean(rdr["hidden"]));
list.Add(p);
}
rdr.Close();
return list;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return null;
}
finally
{
conn.Close();
}
}
If your Client and RepPrefix have settable properties with names that match the database columns, you can avoid the need to write a lot of boilerplate code by using a library like Dapper:
var clients = conn.Query<Client>("SELECT id, clientName, info, hidden from clients;").ToList();
var repPrefixes = conn.Query<RepPrefix>("SELECT id, prefixName, hidden from repPrefix;").ToList();
// ...
class Client
{
public int Id { get; set; }
public string ClientName { get; set; }
public string Info { get; set; }
public bool Hidden { get; set; }
}
It will map from DB column names to C# property names, perform the appropriate type conversions, etc.
If you don't want to use an external library, but want to write the code yourself, I would modify the signature of getData to take a function that takes a DbDataReader and returns an initialized object of type T:
// method that executes the query and invokes a callback to read the data
public List<T> getData<T>(string[] columns, string tableName, Func<DbDataReader, T> readData)
{
var list = new List<T>();
try
{
conn.Open();
string sql = "SELECT " + string.Join(",", columns) + " from " + tableName;
using var cmd = new MySqlCommand(sql, conn);
using var rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// read the data from this row and construct a new T
T t = readData(rdr);
list.Add(p);
}
return list;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return null;
}
finally
{
conn.Close();
}
}
// an example of calling getData with a custom callback that creates Client objects
List<Client> GetClients() =>
getData(new[] { "id", "clientName", "info", "hidden" }, "clients",
rdr => new Client(rdr.GetInt32(0), rdr.GetString(1), rdr.GetString(2), rdr.GetBoolean(3)));
First, I highly recommend Dapper. Dapper will map objects to SQL statements for you and is performant.
If you have classes that align with your db tables, you could use reflection or some function on each class to generate SELECT, INSERT, and UPDATE statements and then use those same objects as your parameters into the Dapper functions.

Web API and Database link C#

I'm currently new to Web APIs and how to work with them. My project consists of a web api that communicates with a DB through Business and Data layers.
First, i have managed to create a controller as show below:
using BusinessLayer;
using BusinessLayer.Models;
namespace ContactService.Controllers
{
public class ContactController : ApiController
{
public void Post([FromBody] Contact contact)
{
Business bu = new Business();
bu.getcontact(contact);
}
}
}
The getcontact function which has Contact as an object:
public void getcontact(Contact c)
{
Data dal = new Data();
dal.ExecuteView(c.Fname,ref c.Lname,ref c.Age,ref c.exist);
}
which gives an error like:
A property, indexer or dynamic member access may not be passed as an out or ref parameter?
And the contact class is:
public class Contact
{
public int ID { get; set; }
public string Fname { get; set; }
public string Lname { get; set; }
public int Age { get; set; }
}
The business layer is connected to the datalayer that manages all sql queries through many functions like:
public void Save(String fname,String lname,String age)
{
if (fname != "" && lname != "" && age != "")
{
Data connect = new Data();
connect.OpenConnection();
connect.ExecuteInsert(fname, lname, age, ref exist);
if (exist)
MessageBox.Show("Name exists");
else
MessageBox.Show("User entered successfully");
connect.CloseConnection();
//connect.isTimer();
}
else
{
MessageBox.Show("Enter all fields");
}
}
public void Del(String fname)
{
if (fname != "")
{
Data connect = new Data();
connect.OpenConnection();
connect.ExecuteDelete(fname, ref exist);
if (exist)
{
MessageBox.Show("Record exists and Deleted");
}
else
MessageBox.Show("Record doesnt exist!");
connect.CloseConnection();
}
else
{
MessageBox.Show("Enter first name!");
}
}
public void View(String fname,ref string lname,ref string age)
{
if (fname != "")
{
Data connect = new Data();
connect.OpenConnection();
connect.ExecuteView(fname, ref lname, ref age, ref exist);
tb1.Text = fname;
tb2.Text = lname;
tb3.Text = age;
if (exist)
{
MessageBox.Show("Infos displayed");
}
else
MessageBox.Show("Name not found");
connect.CloseConnection();
}
else
{
MessageBox.Show("Enter first name!");
}
}
For example, ExecuteView looks like this:
public void ExecuteView(String Fname, ref String lname,ref String age,ref
bool exist)
{
try
{
//using (var command = new SqlCommand("DisplayInfo", con))
using (IDbConnection db = new SqlConnection(c.connstr))
{
if (db.State != ConnectionState.Open)
db.Open();
DynamicParameters param = new DynamicParameters();
param.Add("#Fname", Fname);
param.Add("#exist", dbType: DbType.Boolean, direction:
ParameterDirection.Output);
SqlDbType.int,ParameterDirection.Output);
Client cl = new Client();
cl = con.Query<Client>("DisplayInfo", param, commandType:
CommandType.StoredProcedure).SingleOrDefault();
Fname = cl.Fname;
lname = cl.Lname;
age = cl.Age.ToString();
exist = param.Get<bool>("#exist");
if (db.State != ConnectionState.Closed)
db.Close();
}
}
My question is: After getting to the Business layer, what should i do to execute the datalayer functions through getcontact() function in the businesslayer? And how to execute GET/POST/DELETE?
All help is appreciated :)
I've taken your code and changed it a bit. There is a lot which can be improved, but this will get you started I think.
First your data access class, it should only do data access and if you want to do something with the results, return it back to the business layer. So no void method.
//DAL
public Client ExecuteView(String Fname, ref String lname, ref String age, ref bool exist)
{
try
{
//using (var command = new SqlCommand("DisplayInfo", con))
using (IDbConnection db = new SqlConnection(c.connstr))
{
if (db.State != ConnectionState.Open)
db.Open();
DynamicParameters param = new DynamicParameters();
param.Add("#Fname", Fname);
param.Add("#exist", dbType: DbType.Boolean, direction:
ParameterDirection.Output);
SqlDbType.int, ParameterDirection.Output);
var cl = new Client();
cl = con.Query<Client>("DisplayInfo", param, commandType: CommandType.StoredProcedure).SingleOrDefault();
exist = param.Get<bool>("#exist");
if (db.State != ConnectionState.Closed)
{
db.Close();
}
return client;
}
}
Your business class just calls the data access class and prepares the parameters, if necessary.
//Business
public Client GetContact(Contact contact)
{
var dataAccess = new DataAccess();
var client = dataAccess.ExecuteView(contact.FirstName, ...)
//Do some business logic, if you want.
return client;
}
Only the presentation layer is left (your API) and can look like this.
//Presentation
using BusinessLayer;
using BusinessLayer.Models;
namespace ContactService.Controllers
{
public class ContactController : ApiController
{
public void Post([FromBody] Contact contact)
{
Business bu = new Business();
var client = bu.getcontact(contact);
//Do something with the client, if you want.
Fname = client.Fname;
lname = client.Lname;
age = client.Age.ToString();
}
}
}
Over here you can change the Client object to some kind of viewmodel which you want to return or change the values to a better representation for your client/api.
Just keep in mind every layer has its own responsibility and shouldn't do anything which doesn't fit this responsibility.
Note: In your code you are doing an INSERT and SELECT in the above method. To keep the code clean, this should be handled in two seperate calls. You should split the functionality in the data access class and combine the calls in the business class, something like this.
public Client GetContact(Contact contact)
{
var dataAccess = new DataAccess();
var contactIdentifier = dataAccess.CreateContact(contact.FirstName, ...);
var client = dataAccess.GetContact(contactIdentifier);
//Do some business logic, if you want.
return client;
}
This is poorly structured anyways.you should create a manager class for each object you have in the datalayer. for ex you have contacts object create a class called ContactsManager and it should get all the functions to implement from a reusable Interface.
Fell free to read more about it:
A Complete Introduction to the Data Layer

Update Collection Value with Database in UWP(MVVM)

I have custom collection which contains student_id,student_name,student_mark.And having the table with same columns in the database as well. The design form have some controls for updating the existing student.
Temporarily all the updating operations are done with that custom collection.Lets assume we have 100 students data in collection and database. Any updating operation should reflect in the collection. But what my doubt is how do i update these values with the database before i close the application??
But when i open the application the collection should have all the values which have stored in the database.
But what my doubt is how do i update these values with the database
Firstly, you need to know how to do CRUD operations on MySQL database with uwp app. For this, please reference this sample.
Secondly, according to your description, you have built up a MVVM project to bind a collection data to the view. But you didn't have a data layer for this MVVM structure. For this, you need to create a class for data layer to do GRUD operations, and establish contact with this data service from ViewModel. More details please reference this article.
The class for data layer I wrote according to your description which contains how to read, update and delete data from mysql database is as follows:
public class Student
{
public int Student_id { get; set; }
public string Student_name { get; set; }
public string Student_mark { get; set; }
}
public class DataService
{
static string connectionString;
public static String Name = "Data Service.";
private static ObservableCollection<Student> _allStudents = new ObservableCollection<Student>();
public static ObservableCollection<Student> GetStudents()
{
try
{
string server = "127.0.0.1";
string database = "sakila";
string user = "root";
string pswd = "!QAZ2wsx";
connectionString = "Server = " + server + ";database = " + database + ";uid = " + user + ";password = " + pswd + ";SslMode=None;";
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand getCommand = connection.CreateCommand();
getCommand.CommandText = "SELECT * FROM student";
using (MySqlDataReader reader = getCommand.ExecuteReader())
{
while (reader.Read())
{
_allStudents.Add(new Student() { Student_id = reader.GetInt32(0), Student_name = reader.GetString(1), Student_mark = reader.GetString(2) });
}
}
}
}
catch (MySqlException sqlex)
{
// Handle it :)
}
return _allStudents;
}
public static bool InsertNewStudent(Student newStudent)
{
// Insert to the collection and update DB
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO student(student_id, student_name, student_mark)VALUES(#student_id, #student_name,#student_mark)";
insertCommand.Parameters.AddWithValue("#student_id", newStudent.Student_id);
insertCommand.Parameters.AddWithValue("#student_name", newStudent.Student_name);
insertCommand.Parameters.AddWithValue("#student_mark", newStudent.Student_mark);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
return false;
}
}
public static bool UpdateStudent(Student Student)
{
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Update student Set student_name= #student_name, student_mark=#student_mark Where student_id =#student_id";
insertCommand.Parameters.AddWithValue("#student_id", Student.Student_id);
insertCommand.Parameters.AddWithValue("#student_name", Student.Student_name);
insertCommand.Parameters.AddWithValue("#student_mark", Student.Student_mark);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
// Don't forget to handle it
return false;
}
}
public static bool Delete(Student Student)
{
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Delete from sakila.student where student_id =#student_id";
insertCommand.Parameters.AddWithValue("#student_id", Student.Student_id);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
return false;
}
}
}
For updating the database in TwoWay binding way, we can implement is by invoking the data updating method in
PropertyChanged event as follows:
void Person_OnNotifyPropertyChanged(Object sender, PropertyChangedEventArgs e)
{
organization.Update((StudentViewModel)sender);
}
For the completed demo you can download here.

Connection control in n-tier application

I’m new in N-tier application and I’m trying to understand the way N-tier app works by making an own application.
I read serveral articles about it, but there’s nothing much more than a wall of text (Might I haven’t found the right place).
Although I got a tool that helps generating DAL, BLL classes but it’s just like an ‘outline’. I have no experience of working with DAL, BLL… so I could not do much.
The following is the code that made from generation tool (as I said) and slightly modified by myself.
DAL
Namespace FIRSTAPP.DAL
{
class Teacher
{
clsOLEDB db = new clsOLEDB();
public OleDbDataReader SelectAll()
{
try
{
db.OpenConnection();
return db.Excute("SELECT * FROM TEACHER");
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public OleDbDataReader SelectRow()
{}
}
}
BLL
namespace FIRSTAPP.BLL
{
class Teacher
{
public string Id { get; set; }
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public List< Teacher > SelectAll()
{
DAL.Teacher dalTeacher = new DAL.Teacher();
IDataReader dr = dalTeacher.SelectAll();
List<Teacher> TeacherList = new List<Teacher>();
while (dr.Read())
{
Teacher myTeacher = new Teacher
{
Id = (string)dr["Id"],
FullName = (string)dr["FullName"],
DateOfBirth = (DateTime)dr["DateOfBirth "],
};
TeacherList.Add(myTeacher);
}
dr.Close();
return TeacherList;
}
Public Teacher SelectRow(string TeacherId)
{}
}
}
DBConnector
namespace FIRSTAPP.DB
{
public class clsOLEDB
{
string mConnectionString = #"Provider = Microsoft.JET.OLEDB.4.0; Data Source = .\FirstAppDB.mdb";
OleDbConnection mConnection;
OleDbDataReader dataReader;
OleDbCommand cmdCommand;
public void OpenConnection()
{
mConnection = new OleDbConnection(mConnectionString);
try
{
mConnection.Open();
}
catch
{
throw new Exception("Could not connect to DB");
}
finally
{
if ( mConnection != null )
mConnection.Close();
}
}
public OleDbDataReader Excute(string SQLText)
{
cmdCommand = mConnection.CreateCommand();
cmdCommand.CommandText = SQLText;
try
{
return cmdCommand.ExecuteReader();
}
catch
{
throw new Exception("Has an error when executing");
}
}
public void CloseConnection()
{
mConnection.Close();
}
}
}
My question is:
If we need to fetch data from data source, we have to follow these steps: Open connection -> Reading data -> Close reader -> Close connection.
My problem is I don’t know where do I should put Close connection statement, in BLL or DAL? How to do that? The more detail, it gets better.
Can you spend 1 minutes to take a look at my code. Is it clean enough? Or Does it has any another problem?
Sorry if there’re any mistakes in my English. Thank you very much.

Reduce Multiple Calls To Database

I have a code a base that iterates through a list of records and does the follwing
'select * from Table to see if fields exist
then later in the interation
'select * from Table to retreive some data
then farther down in the interation
select field1, field2 from Table to get certain pieces of information
I need to do all of these functions for each record. Would the process speed up if I called the query once for each record and hold the data in a datatable and retreive what I need from there? Or is there another more efficient way to not have to make 3 db calls to the same table which will speed up the process?
You can cache query data to System.Data.DataTable. To simplify things I has written CMyDynaset class, which populates DataTable with data from DB. Here how to use it for example with MySQL:
using System;
using System.Data.Common;
using MySql.Data.MySqlClient;
namesapce MyProg
{
class Program
{
private const string strMyConnection = "Host=localhost;Database=mydb;User Id=myuser;Password=mypsw";
static void Main(string[] args)
{
using (MySqlConnection myConnection = new MySqlConnection(strMyConnection))
{
using (MyDb.CMyDynaset dyn = new MyDb.CMyDynaset(myConnection, MySqlClientFactory.Instance))
{
// populate dyn.Table (System.Data.DataTable)
dyn.Init("select * from Table");
dyn.Load();
// access fields
foreach (DataColumn column in dyn.Table.Columns)
{
// ...
}
// get data
long nCountAll = dyn.Table.Rows.Count; // rows count
foreach (DataRow row in dyn.Table.Rows)
{
Object val1 = row[1]; // acess by index
Object val2 = row["id"]; // acess by name
// ...
}
// update data
dyn.Table.Rows[0]["name"] = "ABC";
dyn.Update();
}
}
}
}
}
CMyDynaset class (CMyDynaset.cs):
// CMyDynaset.cs
using System;
using System.Data.Common;
namespace MyDb
{
/// <summary>
/// Summary description for CMyDynaset.
/// </summary>
public class CMyDynaset : IDisposable
{
public System.Data.DataTable Table = null;
// private
private DbConnection myConnection = null;
private DbProviderFactory myFactory = null;
private DbDataAdapter dataAdap = null;
private DbCommandBuilder cmdBld = null;
private bool bIsSchema = false;
public CMyDynaset(DbConnection conn, DbProviderFactory factory)
{
this.myConnection = conn;
this.myFactory = factory;
}
#region IDisposable Members
public void Dispose()
{
if (this.Table != null)
{
this.Table.Dispose();
this.Table = null;
}
if (this.cmdBld != null)
{
this.cmdBld.Dispose();
this.cmdBld = null;
}
if (this.dataAdap != null)
{
this.dataAdap.Dispose();
this.dataAdap = null;
}
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
#endregion
// Init
public void Init(string strSelect)
{
DbCommand cmdSel = this.myConnection.CreateCommand();
cmdSel.CommandText = strSelect;
this.dataAdap = this.myFactory.CreateDataAdapter();
this.dataAdap.SelectCommand = cmdSel;
this.cmdBld = this.myFactory.CreateCommandBuilder();
this.cmdBld.DataAdapter = this.dataAdap;
this.Table = new System.Data.DataTable();
// schema
this.bIsSchema = false;
}
public void AddParameter(string name, object value)
{
DbParameter param = this.dataAdap.SelectCommand.CreateParameter();
param.ParameterName = name;
param.Value = value;
this.dataAdap.SelectCommand.Parameters.Add(param);
}
public void AddParameter(DbParameter param)
{
this.dataAdap.SelectCommand.Parameters.Add(param);
}
// Open, Close
private void Open(ref bool bClose)
{
if (this.myConnection.State == System.Data.ConnectionState.Closed)
{
this.myConnection.Open();
bClose = true;
}
if (!this.bIsSchema)
{ // schema
this.dataAdap.FillSchema(this.Table, System.Data.SchemaType.Mapped);
this.bIsSchema = true;
}
}
private void Close(bool bClose)
{
if (bClose)
this.myConnection.Close();
}
// Load, Update
public void Load()
{
bool bClose = false;
try
{
this.Table.Clear();
this.Open(ref bClose);
this.dataAdap.Fill(this.Table);
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
this.Close(bClose);
}
}
public void Update()
{
bool bClose = false;
try
{
this.Open(ref bClose);
this.dataAdap.Update(this.Table);
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
this.Close(bClose);
}
}
}
}

Categories