Reputation: 1403
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
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