Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Class Model

Posted on 2006-04-24
19
Medium Priority
?
326 Views
Last Modified: 2010-04-16
Hello All,
                 I am creating a class called Accounts for my data hub purposes and I will need a few subclasses in that class. Say they will be transactions and positions. They will look like following:

Accounts(acc#).transactions(,,,,  ).mehtods,properties , etc .....     sort of the same logic as in Excel                         workbooks(name).sheets. methods & properties

I know how to create a single class but never dealt with an object model. Can you please show me how?


Thanks,
Sergei
0
Comment
Question by:Autofreak
  • 11
  • 6
  • 2
19 Comments
 
LVL 5

Expert Comment

by:GENTP
ID: 16527802
class Account
{
 private Transaction myTrans;

public Account( )
{
 myTrans = new Transactions();
}

public Transaction Transactions
{
 get{ return myTrans;}
 set { myTrans = value;}
}

}

class Transactions
{
 public int MyMethod()
{
 return 0;
}
}

void main()
{
 Account account = new Account();

// Example
int x = account.Transactions.MyMethod()
}
0
 
LVL 5

Expert Comment

by:GENTP
ID: 16527809
Oops in the Account class it should be:

public Transactions Transaction
{
 get{ return myTrans;}
 set { myTrans = value;}
}
0
 

Author Comment

by:Autofreak
ID: 16548195
Hi,
     I am not sure I see what I asked for and would like to try to apply this sulurion on a real problem.
Say, we have a list of accounts in a ComboBox and the user choses ,for eg. acc# 1000, to look up the number of shares of ABC stock in that portfolio. Tha portfolio data is in a SQL Server table and looks like the following

table1

account     security      shares
1000          AAA           100
1000          ABC            50
1000          AAV            52  

In the client code I would like to access the number of shares = 50 for ABC

it will probably look like

int shares = account.security.shares with prior instantiating of the required objects
OR
int shares = account(1000).security("ABC").shares


Could you please make suggestions on the class implementation strategies for this sort of problem

Thanks
Serge
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 1

Expert Comment

by:weechap
ID: 16551199

You could try something along the lines of the following to achieve the
   int shares = account(1000).security("ABC").shares
type of syntax.

Unfortunately there's a mix of bracket types ( square and round ) in the syntax, but I'm sure this can be ironed out.  The code example below might contain some errors as I don't have a C# compiler to hand to check it, but it gives a general principal, and some ideas...


public MyClass
{
  public void DoGet()
  {
    AccountsAccessor account = new AccountsAccessor();

    account[1000].Security("ABC").Shares;
  }
}

public class AccountHolding
{
  double m_holdingQty;
  string m_stockCode;

  public AccountHolding(int accNo, string stockCode)
  {
    this.LoadData(accNo, stockCode);
  }

  public double Shares
  {
    get { return this.m_holdingQty; }
  }
}

public class Account
{
  int m_accNo;

  public AccountHolding Security(string stockCode)
  {
     return GetAccountHoldingForStock(this.m_accNo, stockCode);
  }

  private AccountHolding GetAccountHoldingForStock(int accNo, string stockCode)
  {
    // Query the Db to return the relevant data for the account and stock
    return new AccountHolding(accNo, stockCode);
  }
}

public class AccountAccessor
{
  private Dictionary<int, Account> m_accList;
  private bool m_useCache = true;

  public Account this[int accNo]
  {
    if (m_useCache)
    {
      return this.m_accList[accNo];
    }
    else
    {
      return this.FetchAccountDataFromDb(accNo);
    }
  }
}


weechap
0
 

Author Comment

by:Autofreak
ID: 16553667
Ok weechap,
                   I am gonna try it and come back with the result.

Regards
Serge
0
 

Author Comment

by:Autofreak
ID: 16564740
weechap,
                AccountAccesor Class doesn't have a constructor. Do you mean it do use the default one. Also, I don't quite understand the Account method and its syntax "public Account this[int accNo] " and neither does C#. As well, what method does this.FetchAccountDataFromDb reference? I don't see a method by the name in the code you supplied. Is it a member of .Net Library?

Thanks
Serge
0
 

Author Comment

by:Autofreak
ID: 16565091
             I figured out that a Get property needs to be added to AccountAccessor Class. this.FetchAccountDataFromDb  is still an unknown reference. Could you please provide explanation for the code, I am not sure I get everything, Class AccountAccessor in particular and the use of Dictionary.

Thanks
Serge


0
 
LVL 1

Accepted Solution

by:
weechap earned 2000 total points
ID: 16628487
Hi there Serge,

Firstly, apologies for not replying earlier - I've been on Holiday for the last week.

The code I provided was really only as an example to illustrate a way in which you could achieve what I thought you were after, and it was somewhat truncated to save space.  

I've attached a version of the code that should comile quite nicely now.

I'm using .NET v2.0.  Dictionary is a new class in .NET that allows for strongly typed collections using a new feature called Generics.  The Dictionary object can be replaced with a Hashtable (as I have done below).

Try the following code.  It compiles OK with VS2005, and I've added some comments to the various classes and methods to help clarify some things.  Hope this helps - let me know if you have any questions...

////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.Text;

namespace AccountsTest
{
      class Program
      {
            static void Main(string[] args)
            {
                  AccountAccessor account = new AccountAccessor();

                  double shares = account[1000].Security("ABC").Shares;
            }
      }

      /// <summary>
      /// An account holding is like an account for shares.  
      /// This class will store the number of shares that are
      /// held of a particular stock in a particular account.
      /// </summary>
      public class AccountHolding
      {
            double m_holdingQty = 0.0;
            string m_stockCode = string.Empty;
            int m_accNo = 0;

            /// <summary>
            /// Loads the Account Holding class.
            /// </summary>
            /// <param name="accNo">The account number with which the holding is associated.</param>
            /// <param name="stockCode">The stock of interest</param>
            public AccountHolding(int accNo, string stockCode)
            {
                  this.LoadData(accNo, stockCode);
            }

            /// <summary>
            /// Returns the number of shares that are held in this particular holding
            /// </summary>
            public double Shares
            {
                  get { return this.m_holdingQty; }
            }

            /// <summary>
            /// Populates the class members with data from the database
            /// </summary>
            /// <param name="accountNumber"></param>
            /// <param name="StockCode"></param>
            private void LoadData(int accountNumber, string StockCode)
            {
                  this.m_accNo = accountNumber;
                  this.m_stockCode = StockCode;

                  // Load the holding's data from the database or where ever the data is held.
            }
      }

      /// <summary>
      /// An account is a client's portfolio.  The Account object will probably be used to track
      /// a client's holdings in individual stocks, as well as any cash transactions.
      /// </summary>
      public class Account
      {
            readonly int m_accNo = 0;

            public Account(int accountNumber)
            {
                  this.m_accNo = accountNumber;
            }

            /// <summary>
            /// Returns a holding of the given stock for this account
            /// </summary>
            /// <param name="stockCode"></param>
            /// <returns></returns>
            public AccountHolding Security(string stockCode)
            {
                  return GetAccountHoldingForStock(this.m_accNo, stockCode);
            }

            /// <summary>
            /// This method constructs a new Account Holding object for the given data
            /// </summary>
            /// <param name="accNo"></param>
            /// <param name="stockCode"></param>
            /// <returns></returns>
            private AccountHolding GetAccountHoldingForStock(int accNo, string stockCode)
            {
                  // Query the Db to return the relevant data for the account and stock
                  return new AccountHolding(accNo, stockCode);
            }
      }


      /// <summary>
      /// This class is used to access Account information.  
      /// The class supports caching of account information if required, although it is very simple.
      ///
      /// The Account Accessor should be used as a standard way to access any account information.
      /// </summary>
      public class AccountAccessor
      {
            /// <summary>
            /// A collection of account objects
            /// </summary>
            private Hashtable m_accList = new Hashtable();

            /// <summary>
            /// A flag indicating if the account data should be saved in a memory cache
            /// </summary>
            private bool m_useCache = true;


            /// <summary>
            /// Used to access account data using the [] notation
            /// </summary>
            /// <param name="accNo"></param>
            /// <returns></returns>
            public Account this[int accNo]
            {
                  get
                  {
                        if (m_useCache)
                        {
                              return this.m_accList[accNo] as Account;
                        }
                        else
                        {
                              return this.FetchAccountDataFromDb(accNo);
                        }
                  }
            }

            /// <summary>
            /// Loads an account object using data from the database
            /// </summary>
            /// <param name="accNo"></param>
            /// <returns></returns>
            private Account FetchAccountDataFromDb(int accNo)
            {
                  // This method will create an Account object and populate
                  // its data directly from the database

                  return new Account(accNo);
            }
      }
}
0
 

Author Comment

by:Autofreak
ID: 16630774
Ok Excellent, working on it.
Regards,
Serge
0
 

Author Comment

by:Autofreak
ID: 16640314
Hello weechap,
                         I got one bug "Object reference not set to an instance of an object"  that is raised in Class Programm on -----> double shares = account[1000].Security("ABC").Shares; -----> pointing to '.Security("ABC")' portion when execution returnes to the line after processing this line ------>return this.m_accList[accNo] as Account; -----> in the read-only propery (AccountAccessor Class).


Could you also please explain the below property and how it works, and its role.


public Account this[int accNo]
          {
               get
               {
                    if (m_useCache)
                    {
                         return this.m_accList[accNo] as Account;
                    }
                    else
                    {
                         return this.FetchAccountDataFromDb(accNo);
                    }
               }
          }




Thank you,
Serge
0
 

Author Comment

by:Autofreak
ID: 16640323
Buy the way, the program compiles fine, it's the run-time when the bug comes up.
Serge
0
 
LVL 1

Expert Comment

by:weechap
ID: 16640442
No worries,

The public Account this[int accNo] property allows you to read and return account data for a given account number value (accNo).
The m_useCache value is simply there to illustrate how you might implement some sort of caching mechanism to improve performance, and it is entirely optional.  Your null reference exception is probably as a result of this feature.  To be safe, you could change the code to be more simple:

  public Account this[int accNo]
  {
    get
    {
      return this.FetchAccountDataFromDb(accNo);
    }
  }

You could call the FetchAccountDataFromDb() method directly in your code, but the this[] property provides a more excel like property.  For example the following would produce the same result (with no caching code):

     class Program
     {
          static void Main(string[] args)
          {
               AccountAccessor account = new AccountAccessor();

               double shares = account[1000].Security("ABC").Shares;
          }
     }

And:

     class Program
     {
          static void Main(string[] args)
          {
               AccountAccessor account = new AccountAccessor();

               double shares = account.FetchAccountDataFromDb(1000).Security("ABC").Shares;
          }
     }

Notice that the difference is the syntax used when reading accounts from the AccountAccessor class.

Does this help at all?
weechap
0
 

Author Comment

by:Autofreak
ID: 16643418
That's cool, I was able to run it. A few more questions on data retrieval.

1. The result of the string  --> double shares = account[1000].Security("ABC").Shares;

is a bouble number that should be assigned to  this.m_holdingQty in the method below. I assignes 500 arbitrarily to get the result other than 0.

private void LoadData(int accountNumber, string StockCode)
        {
            this.m_accNo = accountNumber;
            this.m_stockCode = StockCode;
            this.m_holdingQty = 500;

            // Load the holding's data from the database or where ever the data is held.
        }


 My question is (and it may go beyond the original quetion's scope but is still an integral its part) - To get this value, do I just retrieve a recordset usin ADO.NET like
SELECT shares
FROM holdings_table
WHERE account=1000 AND security="ABC"
GROUP BY security

or did you mean somthing different  ?

2. I don't see that we use the Hashtable anywhere, what role did you intend to give it?


 
0
 
LVL 1

Expert Comment

by:weechap
ID: 16646218
1.  I think you're on the right lines with what you're saying.  Unfortunately I don't know too much about ADO.NET, but I'd expect the load data method to be something like:

     private void LoadData(int accountNumber, string StockCode)
     {
          this.m_accNo = accountNumber;
          this.m_stockCode = StockCode;

          // Load the holding's data from the database or where ever the data is held.

          // Construct an SQL query to read the Account Holding data
          string sqlQuery = string.Format("SELECT ht.shares FROM holdings_table ht WHERE ht.account = {0} AND ht.security = '{1}'", this.m_accNo, this.m_stockCode);

          // Now create a database connection, open it and execute the query.  
          // The resulting dataset should contain the number of shares in this holding.
          // Set the value of this.m_holdingQty from the value in the dataset
     }

2. The hashtable was a part of the caching mechanism.  You can ignore it if you want.
0
 

Author Comment

by:Autofreak
ID: 16650383
Thank you, it's getting clearer, your explanations get me where I hopped I would get .

             I am going to ask you one question that may seem not so clear though. Thing is, I am fairly new to C# and the real OOP overall like some of the technics I saw you using go beyong the material I have covered so far. I am thrilled at how the Classes you built work and imtuitively understand the archetectural idea behind the code but I would like to clarify a few things to know for sure what is going on.

             For instance, I 've gone over inheritance & polymorphism, looked at composition and how it is different from the former. However, the way your classes are designed cannot be explained by what I have seen so far. For example, starting with Class AccountAccessor this is what I observe.

in Class  Program we start with alocating memory for a new object account of AccountAccessor Class that has no data/instance variables (given the no-cache version). Execution jumps right to the next line-----> double shares = account[1000].Security("ABC").Shares; -----<  

public Account this[int accNo]  property in not a usual accessor/property such as, say, public int Property {get {return property;}} where <property> would be a <private int property> instance variable of AccountAccessor Class. Instead, public Account this[int accNo] refers to AcountAccessor Class itself -- this[int accNo] ---  and defines this reference as Account Class type. The AccountAccessor Acass's  get property ends with < return new Account(accNo); that does somthing to account object such that we can access <public AccountHolding Security(string stockCode)>  method of Account Class thru <account[1000].> part of <double shares = account[1000].Security("ABC").Shares;> In this case, thru get propery <return new Account(accNo);>  what happens to account object? Has it morphed into Account Class's object such as account[1000]?


                    This pattern repeats in Account class where methods Security and GetAccountHoldingForStock are of AccountHolding Class the class to which <public AccountHolding Security(string stockCode)> method refers to when in the last step of <account[1000].Security("ABC")> it executes a line like this <return new AccountHolding(accNo, stockCode);> Does it mean that now account[1000].Security("ABC") can be considered as AccountHolding class object and thus can access the Class's property <public double Shares>???


Like I said, I sort of see how it's intended to work but need to get to the bottom of the technology. Sort of lookes like backword polymorphism where classes don't inherit explicely but use other classes' functionality by becoming those classes' objects after some work has been done while enjoying being the preceding class's instance.  

Could you please comment on it.

Regards,
Serge


 
0
 
LVL 1

Expert Comment

by:weechap
ID: 16656040
Wow, you're really into this stuff!

The code example I gave was really only an illustration of how you could achieve what I thought you wanted.  There are lots of potential improvements that can be incorporated in it, but I'll leave those for you to implement !

The this[int index] property is unusual.  It is conventionally used to provide indexed access to an array or collection of objects.  The AccountAccessor class is intended as the way in which Account data is constructed.  In this way it is kind of behaving like a Factory (search for Factory Pattern on google).  The AccountAccessor object contains no data in this example, but in a full application it might contain caching data or db connection data, etc.  It's likely that the AccountAccessor class would be implemented using a Singleton pattern.

You asked the question "What happens to the Account object?".  I'm not sure what you mean by this exactly.  An instance of the Account class is created in the AccountAccessor.  This is returned to the Main method where the Security method is called.  This returns an instance of AccountHolding, which has a property Shares.  As an illustration the Main method can be re-written as:

      static void Main(string[] args)
     {
          // Create an accountFactory so that we can read account data
          AccountAccessor accountFactory;
          accountFactory = new AccountAccessor();

          // Read account number 1000 and store it in a local variable (myAcc)
          Account myAcc;
          myAcc = accountFactory[1000];          // <- Method call 1

          // Read the AccountHolding data for stock ABC from account number 1000 (myAcc) and store the
          // AccountHolding data in a local variable (holding)
          AccountHolding holding;
          holding = myAcc.Security("ABC");          // <- Method call 2

          // Now read the number of shares that the holding has
          double shares;
          shares = holding.Shares;          // <- Method call 3
     }

---------------
> This pattern repeats in Account class where methods Security and GetAccountHoldingForStock
> are of AccountHolding Class the class to which <public AccountHolding Security(string stockCode)>
> method refers to when in the last step of <account[1000].Security("ABC")> it executes a line
> like this <return new AccountHolding(accNo, stockCode);> Does it mean that now
> account[1000].Security("ABC") can be considered as AccountHolding class object and thus can
> access the Class's property <public double Shares>???

Yes.
---------------

I'm not sure what you mean by "backwards polymorphism" exactly. The code example I gave is fairly simple, and it does nothing unusual really.  The line:

     double shares = account[1000].Security("ABC").Shares;

...contains three separate method calls (see the expanded example above).  Each method call returning an instance of a class that can be used in a subsequent call.  The nice thing with C# is that it allows us to wrap up a number of method calls into one line of code.  This can be handy if we want to reduce the amount of code, but it can also be confusing when trying to work out what is going on.

weechap
0
 

Author Comment

by:Autofreak
ID: 16662901
Thank you weechap, I got a notch taller after talkin to you, gimme some time and we will probably continue our discussion in a fresh Q. This one is a strong A++ , thanks for the patience and understanding.

Serge  
0
 
LVL 1

Expert Comment

by:weechap
ID: 16665346
No worries
0
 

Author Comment

by:Autofreak
ID: 16667939
By the way,
                  there's no e-mail in your profile, wanna give it to me case I need your advice? Perhaps alerting you to Q's like this one is rational.  

Cheers,
Serge
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
The Relationships Diagram is a good way to get an overall view of what a database is keeping track of. It is also where relationships are defined. A relationship specifies how two tables connect to each other. As you build tables in Microsoft Ac…
Suggested Courses

564 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question