Wrox Programmer Forums
Go Back   Wrox Programmer Forums > ASP.NET and ASP > ASP.NET 1.0 and 1.1 > ASP.NET 1.1
|
ASP.NET 1.1 As of 10/6/2005, this forum is locked as part of the reorganization described here: http://p2p.wrox.com/topic.asp?TOPIC_ID=35394. No posts have been deleted. Open ongoing discussions from the last week have been moved to either ASP.NET 1.0 and 1.1 Beginners http://p2p.wrox.com/asp-net-1-0-1-1-basics-60/ or ASP.NET 1.0 and 1.1 Professional. http://p2p.wrox.com/forum.asp?FORUM_ID=50. See my sticky post inside for more.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the ASP.NET 1.1 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 21st, 2005, 03:06 PM
Authorized User
 
Join Date: Jan 2005
Posts: 20
Thanks: 0
Thanked 0 Times in 0 Posts
Default Desiging a collection class in c#

This is a shopping cart system I'm building to learn C#.

I have have a Order class and Product class. A order can contain many products... how do I impliment this type of behavior in OOP? I have considered inheirting from the icollection interface - is this the best practice? How would I use the class once icollection was implimented? Im confuzled :S

Thanks!!

-- JQ
 
Old March 21st, 2005, 03:18 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,998
Thanks: 0
Thanked 3 Times in 3 Posts
Default

You can have a class that inherits a list type functionality, you could declare a class that inherits from ICollection. I've used IList for a class, then have functions to add, remove, etc that I need to add and remove items in the list. IList has a "list" property that interacts with the internal list.

You could also use a prebuilt array class, such as Hashtable or ArrayList, or store an array of Product classes.

It's up to you how complex you want to get.

Brian
 
Old March 22nd, 2005, 02:13 PM
Authorized User
 
Join Date: Jan 2005
Posts: 20
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Cool thanks! So if I have a OrderProducts class that inheirts from ICollection I have access to the add, remove etc functionality that comes with a collection. So if I were to do soemthign like this:

OrderProducts.Add(new Product(product));

How would OrderProducts know what to do with the product, and can I add any arbitrary type to that collection or somehow limit it to a particular type?

 
Old March 22nd, 2005, 05:57 PM
Friend of Wrox
 
Join Date: Jul 2004
Posts: 623
Thanks: 0
Thanked 1 Time in 1 Post
Default

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
 
Old March 24th, 2005, 04:32 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,998
Thanks: 0
Thanked 3 Times in 3 Posts
Default

Usually you make it type specific for one type, but in the case for many types, you have to set the parameter to an object. When you add the Product class, it adds the Product to a list object that is retained in the collection. I know when I inherited from CollectionBase, it defined a List property that I would add the items to.

Brian





Similar Threads
Thread Thread Starter Forum Replies Last Post
how to build class structure for collection output jimusa Visual Basic 2005 Basics 3 August 7th, 2008 04:49 PM
return collection by function in class jimusa Visual Basic 2005 Basics 1 July 30th, 2008 03:18 PM
function return collection in class by VB jimusa Visual Studio 2005 1 July 30th, 2008 03:12 PM
Property access from Class within Partial Class zoltac007 C# 2005 0 December 1st, 2006 01:01 AM
Collection Class chapter 5 eggspencer BOOK: Professional PHP 5 ISBN: 978-0-7645-7282-1 1 November 27th, 2006 04:46 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.