Paul
Paul

Reputation: 1403

Linq Query returns object reference exception

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.

Upvotes: 0

Views: 1759

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1503260

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.

Upvotes: 2

Related Questions