1

I have a LINQ query written to pull at least one row from a datatable as follows:

var generalQuery =
      from contact in contacts.AsEnumerable().DefaultIfEmpty()
      where contact.Field<String>("CONTACT_TYPE").ToUpper() == "AGENT"
      select new
          {
          AgentName = contact.Field<String>("FIRST_NAME") + " " +
              contact.Field<String>("LAST_NAME"),
          AgentPhoneNumber = contact.Field<String>("PHONE"),
          AgentEmailAddress = contact.Field<String>("EMAIL")
          };

I then try to set the properties of a new instance of a class with the values in the LINQ query output:

var genInfo = new GeneralInformationType
{
    AgentName = generalQuery.FirstOrDefault().AgentName,
    AgentPhoneNumber = generalQuery.FirstOrDefault().AgentPhoneNumber,
    AgentEmailAddress = generalQuery.FirstOrDefault().AgentEmailAddress
}; 

The problem I am running into is that occasionally there are no results in the query. This tries to set the value of the various strings in GeneralInformationType to null and causes exceptions. I tried various methods of DefaultIfEmpty, but can't figure out where to put it.

Any help would be appreciated.

Thanks, Rob

SpaceCowboy74
  • 1,367
  • 1
  • 23
  • 46

2 Answers2

1

There are two separate problems here. First, DefaultIfEmpty is going to effectively give you a sequence with a null DataRow if the query doesn't return anything. That will then fail not when it tries to assign strings - but when in the Where clause. You're then also using FirstOrDefault which would normally return null if there are no matching entries.

I would personally remove DefaultIfEmpty call, and put all the defaulting in the code for genInfo:

var generalQuery =
       from contact in contacts.AsEnumerable()
       where contact.Field<String>("CONTACT_TYPE").ToUpper() == "AGENT"
       select new
       {
           AgentName = contact.Field<String>("FIRST_NAME") + " " +
               contact.Field<String>("LAST_NAME"),
           AgentPhoneNumber = contact.Field<String>("PHONE"),
           AgentEmailAddress = contact.Field<String>("EMAIL")
       };

// Like using DefaultIfEmpty(...).First()
var result = generalQuery.FirstOrDefault() ?? 
        new { AgentName = "Default",
              AgentPhoneNumber = "Default",
              AgentEmailAddress = "Default" };

var genInfo = new GeneralInformationType
{
    AgentName = result.AgentName,
    AgentPhoneNumber = result.AgentPhoneNumber,
    AgentEmailAddress = result.AgentEmailAddress
}; 

Obviously change "Default" to whatever you want. If you have more specific requirements, please explain what you're trying to do and I'm sure we'll be able to accommodate them...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

I would recommend removing DefaultIfEmpty() in your generalQuery and adding some logic when generalQuery is empty like so:

var generalQuery =
      from contact in contacts.AsEnumerable()
      where contact.Field<String>("CONTACT_TYPE").ToUpper() == "AGENT"
      select new
          {
          AgentName = contact.Field<String>("FIRST_NAME") + " " +
              contact.Field<String>("LAST_NAME"),
          AgentPhoneNumber = contact.Field<String>("PHONE"),
          AgentEmailAddress = contact.Field<String>("EMAIL")
          };

var genInfo = new GeneralInformationType
{
    AgentName = generalQuery.Any() ? generalQuery.First().AgentName : "Default Name",
   ....
}; 
Aducci
  • 26,101
  • 8
  • 63
  • 67
  • Both answers seem correct. I chose this one over Jon's since it was the method I used and didn't require an interim "result" object. Thanks for all your help! – SpaceCowboy74 Aug 02 '11 at 16:32