public class MyDataAccess { #region Declarations private IDbConnection oConnection; private IDbCommand oCommand; private IDbDataAdapter oAdapter; private IDataParameterCollection oParms; public string ConnectionString = ""; protected string ErrorMessage = ""; #endregion #region Constructor/Destructor public MyDataAccess() { MyConnection o = new MyConnection(); this.oConnection = o.GetConnection(); this.ConnectionString = o.ConnectionString; this.oCommand = this.GetIDbCommand(); this.oAdapter = this.GetIDbDataAdapter(this.oCommand); this.oCommand.Connection = this.oConnection; this.oCommand.CommandType = CommandType.StoredProcedure; } #endregion #region Get/Use IDb Interface Objects protected IDbCommand GetIDbCommand() { return new SqlCommand(); } protected IDbDataAdapter GetIDbDataAdapter(IDbCommand command) { return new SqlDataAdapter((SqlCommand)command); } protected IDbDataParameter GetIDbDataParameter(string ParmName, object ParmValue) { return new SqlParameter(ParmName, ParmValue); } protected void DeriveParameters(IDbCommand command) { SqlCommandBuilder.DeriveParameters((SqlCommand)command); } #endregion // Then there are the various protected methods for adding and setting Parameters, filling a DataSet, etc. // It's these various methods that get used in the classes that are sub-classed from this "base" class. // Here's just a few of them: protected void ClearParameters() { this.oCommand.Parameters.Clear(); this.ErrorMessage = ""; } protected void AddParms(string ParmName, object ParmValue) { try { if (ParmName.StartsWith(this.AtSign) == false) ParmName = this.AtSign + ParmName; if (ParmValue != DBNull.Value) this.oCommand.Parameters.Add(this.GetIDbDataParameter(ParmName, ParmValue)); } catch (Exception ex) { this.ErrorMessage += ex.Message; } } protected void AddParms(string ParmName, object ParmValue, ParameterDirection direction) { this.AddParms(ParmName, ParmValue); this.SetParmDirection(ParmName, direction); } protected bool FillData(DataSet ds, string StoredProcName) { try { this.oCommand.CommandText = StoredProcName; this.oAdapter.Fill(ds); } catch (Exception ex) { this.ErrorMessage += ex.Message; this.CloseConnection(); return false; } return true; } }In this way, your DataAccess sub-classes are totally "disassociated" from knowing what your back-end data is (could be SqlServer, as the above class is, but if you also have an Oracle customer, you have another base class exactly the same as the above class, but it uses Oracle-specific stuff instead and you use the appropriate DLL depending on your which database your customer has ... however, you're still programming to the interface (the IDB Interface objects), so your sub-classes, which are in different projects (and thus different DLLs) don't care and don't need to be changed.
public class PersonsAccess : MyDataAccess { #region Public Get Methods public DataSet GetPersonsOnReport(ref string Message, string ReportNumber, string Supplement) { PersonDataSet ds = new PersonDataSet(); this.ClearParameters(); this.AddParms("ReportNumber", ReportNumber); this.AddParms("Supplement", Supplement); this.FillData(ds, "csp_Persons_Get"); return ds; } // more methods #endregion }As you can see, it's not that bad once you get down to actually using it. I hope this gives you some ideas.
>DataSet ds; >DataTable dt; >DataRow dr; >SqlDataAdapter oDataAdapter; >int lnRecords; > >ds = new DataSet(); >this.map_ConnectToData(); > >oDataAdapter = new SqlDataAdapter(); >oDataAdapter.SelectCommand = new SqlCommand("map_rlb_Logins_validate", this.oConnection); >oDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure ; > >oDataAdapter.SelectCommand.Parameters.Add("@tcUserID",SqlDbType.Char, 20).Value = tcLoginID; >oDataAdapter.SelectCommand.Parameters.Add("@tcPassword",SqlDbType.Char, 20).Value = tcPassword; >lnRecords = oDataAdapter.Fill(ds, "cData"); > >MessageBox.Show(lnRecords.ToString()); > >dt = ds.Tables["cData"]; >dr = ds.Tables[0].Rows[0]; > >MessageBox.Show(dr["cuserid"].ToString()); >>