2012-02-12 3 views
0

Я просмотрел некоторые сообщения об этом исключении, появляющемся в коде Linq, но ничто из этого не помогло. Я знаю, что это означает, что я имею в виду нулевое значение где-то, но я установил оператор if, который должен предотвратить ошибку.Linq Query возвращает исключение ссылки на объект

То, что я пытаюсь сделать, это запросить базу данных CRM, но вернуть только три части информации для каждого контакта. Исключение происходит в строке foreach. Вот мой код (ну, не совсем все мое):

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(); 
     } 
    } 
    } 
} 

Сообщите мне, если у вас есть какие-либо идеи. Спасибо.

+0

Непосредственно связано с вашей ошибкой, но также нет необходимости запрашивать учетные записи отдельно от контактов, если все, что вы ищете, это если у контакта есть основная учетная запись. Когда вы отбрасываете информацию о запросе для контакта, «c.parentcustomerid.name» (при условии, что она не является нулевой) должна содержать имя родительской учетной записи. – Matt

ответ

2

Давайте посмотрим на этот запрос:

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

Любой элемент возвращается из этого запроса будет не быть пустым. Таким образом, вы абсолютно не это нужно:

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

new { ... } выражение никогда возвращает нуль.

Но вы можете получить исключение из вашего запроса, если либо c.ParentAccount имеет нулевое значение, или c.Contact равно нулю.

Это не ясно из кода, какой из этих ситуаций может быть, но вы можете изменить ваш запрос:

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 
     }; 

Там в также вероятность того, что c сама по себе нуль здесь - если cnts содержит какие-либо нулевые ссылки. Вы можете игнорировать все эти элементы легко:

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 
     }; 

... но было бы лучше, чтобы убедиться, что ваша коллекция не имеет нулевые элементы, чтобы начать с.

+0

не может быть пустым, как в моем коде? – Hogan

+0

@Hogan: Нет - 'Select' никогда не вернет null. –

+0

@Hogan также возможно, что c.ParentAccount и c.Contact не являются нулевыми, но свойство name, lastname или firstname равно null. – phoog

Смежные вопросы