JenniQ,
in your case its better to have some prebuilt collection i.e arraylist saves a list of objects,hashtable can accept entries which could be enough fast for getting the value,and sortedlist is a sortedhashtable look into MSDN to see what interfaces they implement
it's better to see an example
suppose for Northwind database we have Category,Product,Supplier..now take a look at this sample codes,
implementation for Product table
Code:
using System;
namespace NwtLibrary
{
/// <summary>
/// Summary description for Product.
/// </summary>
public class Product
{
private int _ProductID;
private string _Name;
private int _SupplierID;
private int _CategoryID;
private string _QuantityPerUnit;
private Decimal _UnitPrice;
private short _UnitsInStock;
private short _UnitsOnOrder;
private short _ReorderLevel;
private bool _Discontinued;
public int ProductID
{
get {return _ProductID;}
set {_ProductID = value;}
}
public string Name
{
get {return _Name;}
set {_Name = value;}
}
public int SupplierID
{
get {return _SupplierID;}
set {_SupplierID = value;}
}
public int CategoryID
{
get {return _CategoryID;}
set {_CategoryID = value;}
}
public string QuantityPerUnit
{
get {return _QuantityPerUnit;}
set {_QuantityPerUnit = value;}
}
public Decimal UnitPrice
{
get {return _UnitPrice;}
set {_UnitPrice = value;}
}
public short UnitsInStock
{
get {return _UnitsInStock;}
set {_UnitsInStock = value;}
}
public short UnitsOnOrder
{
get {return _UnitsOnOrder;}
set {_UnitsOnOrder = value;}
}
public short ReorderLevel
{
get {return _ReorderLevel;}
set {_ReorderLevel = value;}
}
public bool Discontinued
{
get {return _Discontinued;}
set {_Discontinued = value;}
}
public Product (int ProductID
, string Name
, int SupplierID
, int CategoryID
, string QuantityPerUnit
, Decimal UnitPrice
, short UnitsInStock
, short UnitsOnOrder
, short ReorderLevel
, bool Discontinued)
{
_ProductID = ProductID;
_Name = Name;
_SupplierID = SupplierID;
_CategoryID = CategoryID;
_QuantityPerUnit = QuantityPerUnit;
_UnitPrice = UnitPrice;
_UnitsInStock = UnitsInStock;
_UnitsOnOrder = UnitsOnOrder;
_ReorderLevel = ReorderLevel;
_Discontinued = Discontinued;
}
}
}
implementation for Category table
Code:
using System;
namespace NwtLibrary
{
public class Category
{
private int _CategoryID;
private string _CategoryName;
private string _Description;
public int CategoryID
{
get {return _CategoryID;}
set {_CategoryID = value;}
}
public string CategoryName
{
get {return _CategoryName;}
set {_CategoryName = value;}
}
public string Description
{
get {return _Description;}
set {_Description = value;}
}
public Category()
{
}
public Category(int CategoryID, string CategoryName, string Description) : base()
{
_CategoryID = CategoryID;
_CategoryName = CategoryName;
_Description = Description;
}
}
}
implementation for Supplier table
Code:
using System;
namespace NwtLibrary
{
public class Supplier
{
private int _SupplierID;
private string _CompanyName;
private string _ContactName;
private string _Address;
private string _City;
private string _Region;
private string _PostalCode;
private string _Country;
private string _Phone;
private string _Fax;
private string _HomePage;
public int SupplierID
{
get {return _SupplierID;}
set {_SupplierID = value;}
}
public string CompanyName
{
get {return _CompanyName;}
set {_CompanyName = value;}
}
public string ContactName
{
get {return _ContactName;}
set {_ContactName = value;}
}
public string Address
{
get {return _Address;}
set {_Address = value;}
}
public string City
{
get {return _City;}
set {_City = value;}
}
public string Region
{
get {return _Region;}
set {_Region = value;}
}
public string PostalCode
{
get {return _PostalCode;}
set {_PostalCode = value;}
}
public string Country
{
get {return _Country;}
set {_Country = value;}
}
public string Phone
{
get {return _Phone;}
set {_Phone = value;}
}
public string Fax
{
get {return _Fax;}
set {_Fax = value;}
}
public string HomePage
{
get {return _HomePage;}
set {_HomePage = value;}
}
public Supplier (int SupplierID
, string CompanyName
, string ContactName
, string Address
, string City
, string Region
, string PostalCode
, string Country
, string Phone
, string Fax
, string HomePage)
{
_SupplierID = SupplierID;
_CompanyName = CompanyName;
_ContactName = ContactName;
_Address = Address;
_City = City;
_Region = Region;
_PostalCode = PostalCode;
_Country = Country;
_Phone = Phone;
_Fax = Fax;
_HomePage = HomePage;
}
}
}
now we have our main class which handle those three structures for our tables
implementation for ProductInfo,
[code]
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
namespace NwtLibrary
{
public class ProductInfo
{
// mProducts holds the cached products table
private SortedList mProducts; // holds the cached categories table
private SortedList mCategories; // holds the cached suppliers table
private SortedList mSuppliers; // holds the date and time the data was last loaded
private DateTime mLastLoaded; // holds the SQL Database connection string
private string mSqlConnStr;
// LOADSTATEMENT is the SQL statement we will execute
// whenever we want to load data from the database into
// into our local cache of objects. This is a constant
private const string LOADSTATEMENT = "SET NOCOUNT ON;" +
"SELECT CategoryID, CategoryName, Description FROM Categories " +
"ORDER BY CategoryID;" +
"SELECT ProductID, ProductName, SupplierID, CategoryID, " +
"QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, " +
"ReorderLevel, Discontinued FROM Products ORDER BY ProductID;" +
"SELECT SupplierID, CompanyName, ContactName, Address, City, " +
"Region, PostalCode, Country, Phone, Fax, HomePage FROM Suppliers " +
"ORDER BY SupplierID;";
public ProductInfo(string SqlConnStr)
{
// Create SortedLists for caching data
mProducts = new SortedList();
mCategories = new SortedList();
mSuppliers = new SortedList();
mLastLoaded = new DateTime();
// Throw an exception if the Database connection string
// provided is of zero-length
// Otherwise, populate the Database connection string
if (SqlConnStr.Length == 0)
throw new ArgumentNullException("The database connection string cannot be zero-length");
else
mSqlConnStr = SqlConnStr;
try
{
// Load the cache from the Database
LoadFromDatabase();
}
catch (SqlException SqlExc)
{
throw SqlExc;
}
catch (Exception Exc)
{
throw Exc;
}
}
#region Properties
// Exposes the LastLoaded information for use
public DateTime LastLoaded
{
get {return mLastLoaded;}
}
// Exposes the SQL Database connection string for use
public string SqlConnStr
{
get {return mSqlConnStr;}
}
// Allows access to the cached version of the categories table
public SortedList Categories
{
get {return mCategories;}
set {mCategories = value;}
}
// Allows access to the cached version of the products table
public SortedList Products
{
get {return mProducts;}
set {mProducts = value;}
}
// Allows access to the cached version of the suppliers table
SortedList Suppliers
{
get {return mSuppliers;}
set {mSuppliers = value;}
}
#endregion
public void LoadFromDatabase()
{
SqlConnection conn = new SqlConnection(mSqlConnStr);
SqlCommand cmd = null;
SqlDataReader sqlDR;
if (mCategories.Count > 0)
mCategories.Clear();
if (mProducts.Count > 0)
mProducts.Clear();
if (mSuppliers.Count > 0)
mSuppliers.Clear();
try
{
if (mSqlConnStr.Length == 0)
throw new Exception("SQL Connection string cannot be zero-length");
cmd = new SqlCommand(LOADSTATEMENT, conn);
cmd.CommandType = CommandType.Text;
conn.Open();
sqlDR = cmd.ExecuteReader(CommandBehavior.CloseConnection) ;
LoadCategories(sqlDR);
LoadProducts(sqlDR);
LoadSuppliers(sqlDR);
mLastLoaded = DateTime.Now;
}
catch (SqlException SqlExc)
{
// Error handling code
Console.WriteLine(SqlExc.ToString());
}
catch (Exception Exc)
{
// Error handling code
Console.WriteLine(Exc.ToString());
}
finally
{
if (cmd != null)
cmd.Cancel();
if (conn != null)
if (conn.State != ConnectionState.Closed)
conn.Close();
}
}
// Loads the data from the database by calling
// the parameter-less version of this method.
// It sets the database connection string up first.
public void LoadFromDatabase(string SqlConnStr)
{
if (SqlConnStr.Length > 0)
mSqlConnStr = SqlConnStr;
try
{
LoadFromDatabase();
}
catch (SqlException SqlExc)
{
throw SqlExc;
}
catch (Exception Exc)
{
throw Exc;
}
}
private void LoadCategories(SqlDataReader SqlDR)
{
try
{
while (SqlDR.Read())
{
// Provide some default values
int CategoryID = 0;
string CategoryName = "";
string Description = "";
if (!SqlDR.IsDBNull(0))
CategoryID = SqlDR.GetInt32(0);
if (!SqlDR.IsDBNull(1))
CategoryName = SqlDR.GetString(1);
if (!SqlDR.IsDBNull(2))
Description = SqlDR.GetString(2);
mCategories.Add(CategoryID,
new Category(CategoryID, CategoryName, Description));
}
SqlDR.NextResult();
}
catch (SqlException SqlExc)
{
// Error handling code
Console.WriteLine(SqlExc.ToString());
}
catch (Exception Exc)
{
// Error handling code
Console.WriteLine(Exc.ToString());
}
}
// Loads the rows of products into the local cache
private void LoadProducts(SqlDataReader SqlDR)
{
try
{
while (SqlDR.Read())
{
// Provide some default values
int ProductID = 0;
string Name = "";
int SupplierID = 0;
int CategoryID = 0;
string QuantityPerUnit = "";
Decimal UnitPrice = 0;
short UnitsInStock = 0;
short UnitsOnOrder = 0;
short ReorderLevel = 0;
bool Discontinued = true;
// Fetch each field from the result set
if (!SqlDR.IsDBNull(0))
ProductID = SqlDR.GetInt32(0);
if (!SqlDR.IsDBNull(1))
Name = SqlDR.GetString(1);
if (!SqlDR.IsDBNull(2))
SupplierID = SqlDR.GetInt32(2);
if (!SqlDR.IsDBNull(3))
CategoryID = SqlDR.GetInt32(3);
if (!SqlDR.IsDBNull(4))
QuantityPerUnit = SqlDR.GetString(4);
// Allow the UnitPrice is actual of type SqlMoney,
// we will just fetch it into decimal as recommended
if (!SqlDR.IsDBNull(5))
UnitPrice = (Decimal)SqlDR.GetDecimal(5);
if (!SqlDR.IsDBNull(6))
UnitsInStock = SqlDR.GetInt16(6);
if (!SqlDR.IsDBNull(7))
UnitsOnOrder = SqlDR.GetInt16(7);
if (!SqlDR.IsDBNull(8))
ReorderLevel = SqlDR.GetInt16(8);
if (!SqlDR.IsDBNull(9))
Discontinued = SqlDR.GetBoolean(9);
// Create a new instance of the product class, then
// append that to the local cache
mProducts.Add(ProductID, new Product(ProductID,
Name,
SupplierID,
CategoryID,
QuantityPerUnit,
UnitPrice,
UnitsInStock,
UnitsOnOrder,
ReorderLevel,
Discontinued));
}
// Move to the next result set in the data stream
SqlDR.NextResult();
}
catch (SqlException SqlExc)
{
throw SqlExc;
}
catch (Exception Exc)
{
throw Exc;
}
}
// Loads the rows of suppliers into the local cache
private void LoadSuppliers(SqlDataReader SqlDR)
{
try
{
while (SqlDR.Read())
{
// Provide some default values
int SupplierID = 0;
string CompanyName = "";
string ContactName = "";
string Address = "";
string City = "";
string Region = "";
string PostalCode = "";
string Country = "";
string Phone = "";
string Fax = "";
string HomePage = "";
// Fetch each field from the result set
if (!SqlDR.IsDBNull(0))
SupplierID = SqlDR.GetInt32(0);
if (!SqlDR.IsDBNull(1))
CompanyName = SqlDR.GetString(1);
if (!SqlDR.IsDBNull(2))
ContactName = SqlDR.GetString(2);
if (!SqlDR.IsDBNull(3))
Address = SqlDR.GetString(3);
if (!SqlDR.IsDBNull(4))
City = SqlDR.GetString(4);
if (!SqlDR.IsDBNull(5))
Region = SqlDR.GetString(5);
if (!SqlDR.IsDBNull(6))
PostalCode = SqlDR.GetString(6);
if (!SqlDR.IsDBNull(7))
Country = SqlDR.GetString(7);
if (!SqlDR.IsDBNull(8))
Phone = SqlDR.GetString(8);
if (!SqlDR.IsDBNull(9))
Fax = SqlDR.GetString(9);
if (!SqlDR.IsDBNull(10))
HomePage = SqlDR.GetString(10);
// Create a new instance of the supplier class, then
// append that to the local cache
mSuppliers.Add(SupplierID, new Supplier(SupplierID,
CompanyName,
ContactName,
Address,
City,
Region,
PostalCode,
Country,
Phone,
Fax,
HomePage));
}
// Move to the next result set in the data stream
SqlDR.NextResult();
}
catch (SqlException SqlExc)
{
throw SqlExc;
}
catch (Exception Exc)
{
throw Exc;
}
}
// Trims excess spaces and replace any single quotes with
// two single quotes. This makes a string ready to use in
// SQL insert and update statements
private string PrepareStringForSql(string val )
{
val = val.Trim();
val = val.Replace("'", "''");
return val;
}
// Returns "1" if the boolean value is true, "0" otherwise
// Handy for inserting booleans in SQL Server bit fields
private string BooleanToSqlBit(bool Flag)
{
if (Flag)
return "1";
else
return "0";
}
// Compares provided values against database and business rules.
// If any rule is violated, an exception is thrown
private bool ValidateBusinessRules(int ProductID
, string ProductName
, int SupplierID
, int CategoryID
, string QuantityPerUnit
, bool Discontinued)
{
// A product name must be supplied, and it must be 40 or less characters long
if (ProductName.Length == 0)
throw new Exception("A product name is required for ProductID " + ProductID.ToString());
if (ProductName.Length > 40)
throw new Exception("A product name of 40 or less characters required for ProductID " + ProductID.ToString());
// A quantity per unit must be provided and must be not more than 20 characters long
if (QuantityPerUnit.Length == 0)
throw new Exception("A Quantity Per Unit is required for ProductID " + ProductID.ToString());
if (QuantityPerUnit.Length > 20)
throw new Exception("A Quantity Per Unit of 20 or less characters required for ProductID " + ProductID.ToString());
// A product must be clearly discountinued or otherwise
if (Discontinued.Equals(null))
throw new NullReferenceException("A porudct must be either discontinued or active");
// If a CategoryID is given, it must exist in the current cache
// of category information
if (!CategoryID.Equals(null))
if (!mCategories.ContainsKey(CategoryID))
throw new DataException("The given CategoryID value of " + CategoryID.ToString() + " is not a known category");
// If a SupplierID is given, it must exist in the current cache
// of supplier information
if (!SupplierID.Equals(null))
if (!mSuppliers.ContainsKey(SupplierID))
throw new DataException("The given SupplierID value of " + SupplierID.ToString() + " is not a known supplier");
return true;
}
public Product UpdateProduct(int ProductID
, string Name
, int SupplierID
, int CategoryID
, string QuantityPerUnit
, Decimal UnitPrice
, short UnitsInStock
, short UnitsOnOrder
, short ReorderLevel
, bool Discontinued)
{
SqlConnection conn = null;
SqlCommand cmd = null;
Product prod;
if (mSqlConnStr.Length == 0)
throw new Exception("SQL Connection string cannot be zero-length");
if (!mProducts.Contains(ProductID))
throw new Exception("Unknown and non-updateable ProductID of " +
ProductID.ToString() + " used.");
try
{
if (ValidateBusinessRules(ProductID, Name, SupplierID, CategoryID,
QuantityPerUnit, Discontinued))
{
cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SET NOCOUNT ON;" +
"UPDATE Products SET " +
"ProductName = '" + PrepareStringForSql(Name.ToString()) + "'," +
"SupplierID = " + SupplierID.ToString() + "," +
"CategoryID = " + CategoryID.ToString() + "," +
"QuantityPerUnit = '" +
PrepareStringForSql(QuantityPerUnit.ToString()) + "'," +
"UnitPrice = " + UnitPrice.ToString() + "," +
"UnitsInStock = " + UnitsInStock.ToString() + "," +
"UnitsOnOrder = " + UnitsOnOrder.ToString() + "," +
"ReorderLevel = " + ReorderLevel.ToString() + "," +
&n