0

I've looked at some of the posts on here about this exception popping up in Linq code but none of it has helped. I'm aware that it means I'm referring to a null value somewhere, but I've set up an if statement which should prevent the error.

What I'm trying to do is query the CRM database but return only three pieces of information per contact queried. The exception occurs at the foreach line. Here is my code (well, not really all mine):

class Program
{
    private static List<account> accs = new List<account>();
    private static List<CrmContact> cnts = new List<CrmContact>();

    static void Main(string[] args)
    {
        if (!CRMConnectionHelper.Authenticate()) throw new Exception("Authentication on CRM Server was NOT successful.");
        Console.WriteLine("Authentication on CRM Server was successful.");

        GetAllAccounts();
        GetActiveContacts();
        QueryDB();
    }

    private static void QueryDB()
    {
        var m = from c in cnts

                select new
                {
                    acct = c.ParentAccount.name,
                    last = c.Contact.lastname,
                    first = c.Contact.firstname
                };

            List<string> lines = new List<string>();

            try
            {
                foreach (var c in m) **Exception here**
                {
                    if (c != null)
                    {
                        //string sub = c1.first.PadRight(10).Substring(0, 3); // Object ref ex here. 
                        lines.Add(string.Format("{0}\t{1}\t{2}", c.acct, c.last, c.first));
                        Console.WriteLine(c.acct);
                        System.Threading.Thread.Sleep(100);
                    }
                    else
                    {
                        Console.WriteLine("c is null. continuing.");
                        continue;
                    }
                }

                Console.WriteLine("Writing list contents to .txt ...");
                System.IO.File.WriteAllLines(@"C:\Documents and Settings\paldrich\Desktop\lines1.txt", lines.ToArray());
                Console.WriteLine("Finished. Press ENTER to exit.");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(String.Format("Error: {0}", ex));
            }   
        }

    private static void GetAllAccounts()
    {
        ColumnSet colsAcc = new ColumnSet { Attributes = new string[] { "accountid", "name", "statecode" } };
        QueryExpression accountQuery = new QueryExpression { EntityName = EntityName.account.ToString(), ColumnSet = colsAcc };
        BusinessEntityCollection accounts = CRMConnectionHelper.crmService.RetrieveMultiple(accountQuery);
        Console.WriteLine(String.Format("Total number of accounts {0}", accounts.BusinessEntities.Length));
        for (int i = 0; i < accounts.BusinessEntities.Length; i++) { accs.Add((account)accounts.BusinessEntities[i]); }
    }

    private static void GetActiveContacts()
    {
        try
        {
            ColumnSet cols = new ColumnSet { Attributes = new string[] { "contactid", "parentcustomerid", "firstname", "middlename", "lastname", "suffix", "emailaddress1", "emailaddress2", "emailaddress3", "statecode", "caad_duplicateid" } };
            ConditionExpression condition = new ConditionExpression { AttributeName = "statecode", Operator = ConditionOperator.Equal, Values = new string[] { "Active" } };
            FilterExpression filter = new FilterExpression { FilterOperator = LogicalOperator.And, Conditions = new ConditionExpression[] { condition } };
            QueryExpression contactQuery = new QueryExpression { EntityName = EntityName.contact.ToString(), ColumnSet = cols, Criteria = filter };
            BusinessEntityCollection contacts = CRMConnectionHelper.crmService.RetrieveMultiple(contactQuery); //Exception: server cannot process request
            int qty = contacts.BusinessEntities.Length;
            Console.WriteLine(String.Format("Total number of contacts {0}", qty));
            for (int i = 0; i < qty; i++)
            {

                try
                {
                    contact c = (contact)contacts.BusinessEntities[i];
                    account ac = new account();
                    if (c.parentcustomerid != null)
                    {
                        ac = (account)(from a in accs where a.accountid.Value == c.parentcustomerid.Value select a).FirstOrDefault();
                        cnts.Add(new CrmContact(ac, c));
                    }
                    else
                    {
                        cnts.Add(new CrmContact(null, c));
                    }

                }
                catch (Exception ex)
                {

                    Console.WriteLine(String.Format("GetActiveContacts: Error for i={0} : {1}", i, ex.Message));
                    Console.Read();
                }
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine(String.Format("Exception occured trying to get active contacts: {0}", ex));
            Console.Read();
        }
    }
    }
}

Let me know if you have any insights. Thank you.

1
  • Not directly related to your error, but there's also no need to query for accounts separately from contacts, if all you're looking for is if the contact has a primary account. When you pull back the query information for the contact, "c.parentcustomerid.name" (assuming it's not null) should contain the name of the parent account. Commented Feb 12, 2012 at 18:09

1 Answer 1

2

Let's look at this query:

var m = from c in cnts
        select new
        {
            acct = c.ParentAccount.name,
            last = c.Contact.lastname,
            first = c.Contact.firstname
        };

Any element returned from this query will not be null. So you absolutely don't need this:

foreach (var c in m)
{
    if (c != null)

A new { ... } expression never returns null.

But you can get an exception from your query if either c.ParentAccount is null, or c.Contact is null.

It's not clear from your code which of those situations it might be, but you could change your query to:

var m = from c in cnts
        select new
        {
            acct = c.ParentAccount == null ? "" : c.ParentAccount.name,
            last = c.Contact == null ? "" : c.Contact.lastname,
            first = c.Contact == null ? "" : c.Contact.firstname
        };

There's also the possibility that c itself is null here - if cnts contains any null references. You could ignore all such elements easily:

var m = from c in cnts
        where c != null
        select new
        {
            acct = c.ParentAccount == null ? "" : c.ParentAccount.name,
            last = c.Contact == null ? "" : c.Contact.lastname,
            first = c.Contact == null ? "" : c.Contact.firstname
        };

... but it would be better to ensure that your collection didn't have any null elements to start with.

Sign up to request clarification or add additional context in comments.

6 Comments

@Hogan: No - Select will never return null.
@Hogan it is also possible that c.ParentAccount and c.Contact are non-null but that the name, lastname, or firstname property is null.
@phoog: While that's true, it wouldn't cause an exception at the point indicated.
@JonSkeet Confusion! I was looking at the line "Object ref ex here." rather than the line "Exception here".
That's my bad, the "object ref ex here" bit is old comment. Thanks for this, I can't test it until Tuesday but will let you know what happens...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.