Linq Query возвращает исключение ссылки на объект - PullRequest
0 голосов
/ 12 февраля 2012

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

То, что я пытаюсь сделать, - это запросить базу данных 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();
        }
    }
    }
}

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

1 Ответ

2 голосов
/ 12 февраля 2012

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

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)

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

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

...