tags:

views:

90

answers:

4

Hi.

I need help with accessing class properties within a given class.

For example, take the below class:

public partial class Account
    {
        private Profile _profile;
        private Email _email;
        private HostInfo _hostInfo;

        public Profile Profile
        {
            get { return _profile; }
            set { _profile = value; }
        }

        public Email Email
        {
            get { return _email; }
            set { _email = value; }
        }

        public HostInfo HostInfo
        {
            get { return _hostInfo; }
            set { _hostInfo = value; }
        }

In the class "Account" exists a bunch of class properties such as Email or Profile. Now, when I want to access those properties at run-time, I do something like this (for Email):

    _accountRepository = ObjectFactory.GetInstance<IAccountRepository>();
    string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify");
    Account account = _accountRepository.GetAccountByUserName(username);

    if(account != null)
    {
        account.Email.IsConfirmed = true;

But, I get "Object reference not set..." for account.Email... Why is that? How do I access Account such that account.Email, account.Profile, and so on returns the correct data for a given AccountId or UserName.

    Here is a method that returns Account:

public Account GetAccountByUserName(string userName)
{
    Account account = null;

    using (MyDataContext dc = _conn.GetContext())
    {
        try
        {
            account = (from a in dc.Accounts
                       where a.UserName == userName
                       select a).FirstOrDefault();
        }
        catch
        {
            //oops
        }
    }

    return account;

}

The above works but when I try:

 account = (from a in dc.Accounts
               join em in dc.Emails on a.AccountId equals em.AccountId
               join p in dc.Profiles on em.AccountId equals p.AccountId
               where a.UserName == userName
               select a).FirstOrDefault();

I am still getting object reference exceptions for my Email and Profile
properties. Is this simply a SQL problem or is there something else I need to be doing to be able to fully access all the properties within my Account class?

Thanks!

+3  A: 

Your getting this because Email is another class which has not been assigned yet. What you can do is in your constructor default the properties that link to other classes as new items. For example in your ctor:

public Account()
{
   // Set Defaults
   Email = new Email();
   Profile = new Profile();
   HostInfo = new HostInfo();
}

Then you can set their values as desired.

Gary L Cox Jr
+2  A: 

This looks like a case of handling null values on your properties. You should initialize the Email property to something other than null if you expect to store or query against it, or alter the queries so that they can expect to deal with null values. Also if you get a null value from the database, and your property cannot be set to null, the reverse problem occurs.

JYelton
A: 

Just wanted to add: there is now a shorter form for declaring trivial properties:

public Profile Profile { get; set; }
public Email Email { get; set; }
public HostInfo HostInfo { get; set; }
BlueRaja - Danny Pflughoeft
"there is *now* "? Auto properties was introduced in C# 3, which was released in November 2007... This is *ancient*! ;-) It's handy if you have a C#3^ compiler though..
Patrick
A: 

Are you declaring these properties yourself, or are you trying to indicate something like auto-generated code from like Linq-to-SQL?

If this is auto-generated where the Account table references the Email table, etc., then you probably just need to specify that you want those objects to load as well in the load options:

using (MyDataContext dc = _conn.GetContext())
{
    var options = new DataLoadOptions();
    options.LoadWith<Account>(a => a.Email);
    options.LoadWith<Account>(a => a.Profile);
    options.LoadWith<Account>(a => a.HostInfo);

    dc.LoadOptions = options;

    try
    {
        account = (from a in dc.Accounts
                   where a.UserName == userName
                   select a).FirstOrDefault();
    }
    catch
    {
        //oops
    }
}
Jim B-G
Jim - I like that but am not quite sure how to do the auto-generated part. Right now, a.Email does not exist as a LINQ table. It does, however, exist when I am referring to my Account.cs class, but I don't think that is what you are talking about. How do I do this completely through LINQ? Thanks again.
Code Sherpa
OK, never mind, i figured it out. Testing now...
Code Sherpa
Jim - using this model, how do I access columns of referenced tables. For example: account.Email.IsConfirmed. When I instantiate the LINQ table, It is showing me all the referenced tables - account.Emails - but "Emails" isn't showing me the columns. How do I do this?
Code Sherpa
My answer really only applies if you are using LINQ to SQL, where the tool generates your model objects for you. In that case, the model objects will already have the associations created. In that case, if Account -> Email was 1-to-1, you would already have an Account.Email property. If Account -> Email was 1-to-many, you would have Account.Emails. Here you are telling it to not only pull back the Account object, but to also populate the related objects as well.
Jim B-G
If Email, Profile, etc. don't exist in the db (so they are your own objects you added in code), then you are responsible for instantiating them.In your original code, var account = new Account() will instantiate a new Account object, but Email, Profile, etc. will be null (they have not been instantiated).If they are your own classes/properties, you need to instantiate them.
Jim B-G
Thanks Jim. I am using LINQ and understand what you are talking about up to the referenced LINQ object's property access. Account and Email are 1 to Many so, I have Account.Emails. From your answer, it still isn't clear to me how to access Account.Emails.IsConfirmed - the columns within Email - for a given instance of account. Can you provide a code example?
Code Sherpa
Thanks - I understand about instantiating my classes but am still not sure about how to access the properties of my LINQ objects. I am missing something here...
Code Sherpa