>LINQ Operators – Part IX

>

Element operators:

First, FirstOrDefault: Used to return the first element from a sequence. T-SQL counterpart is "top 1".

Last, LastOrDefault: Used to return the last element from a sequence. T-SQL counterpart is "top 1 … order by desc"

Single, SingleOrDefault; Used the return the single result from a sequence. Similar to First/FirstOrDefault but this one throws an exception if there are more than 1 results.

Using these methods you can either get First, Last or Single element from a sequence ( like a "locate" without any additional clause ). Or you can use a boolean predicate to filter "for" a match. Sometimes there wouldn’t be a match to the predicate you supplied and no element would be returned from a sequence. That would cause an exception to be thrown unless you have used the FirstOrDefault, LastOrDefault or SingleOrDefault. "Or default" versions return an element from sequence a default( TSource ) – which is "null" for reference types like string, Customer and blank for value types (generally 0). 

Customers.Where( c => c.Country == "UK")
Returns a sequence of Customers whether it may be 0 or more Customers. We could get the first UK customer as a single element of Customers type using First like this:
Customers.Where( c => c.Country == "UK").First()
or:
Customers.First( c => c.Country == "UK" )
 
Since the result is now an element we could directly get its properties if we wanted to like:
Customers.First( c => c.Country == "UK" ).CompanyName

The problem with First() is that if the country was something like "Turkey" (there is no customer from Turkey in Northwind sample database) then the sequence that First() would operate on would have no elements to choose from hence an exception would be thrown. FirstOfDefault() on the other hand, would return a default Customers element:

Customers.First( c => c.Country == "Turkey" ) // throws exception

Customers.FirstOrDefault( c => c.Country == "Turkey" ) // default Customers element – null

Last and LastOrDefault works like First/FirstOrDefault but is not supported in Linq To SQL.

int[] numbers = {3,8,6,8,3,4,7};
numbers.Last( n => n % 2 == 0).Dump(); // 4

Single and SingleOrDefault is useful when we are getting data using a unique key (typically a primary key):

string id1 = "BONAP";
string id2 = "XXXXX";

Customers customer1 = 
  Customers
  .SingleOrDefault( c => c.CustomerID == id1);

Customers customer2 = 
  Customers
  .SingleOrDefault( c => c.CustomerID == id2);

( customer1 == null 
  ? "No such customer exists." 
  : customer1.CompanyName ).Dump("Key:" + id1);
  
( customer2 == null 
  ? "No such customer exists." 
  : customer2.CompanyName ).Dump("Key:" + id2);

 

ElementAt, ElementAtOrDefault: Similar to other element operators, returns element at Nth position (or default(T) with ElementAtOrDefault when there is no element at given position). Not supported in Linq To SQL. You can think of it as record number or array position:

IEnumerable<Customers> cus = Customers.AsEnumerable();

cus.ElementAtOrDefault( 34 ).Dump("34th"); // HILAA
cus.ElementAtOrDefault( 134 ).Dump("134th"); // null

 

 DefaultIfEmpty: Is used for returning a default(TSource) when the sequence is empty (normally it would return a "sequence" if existed). Used in "left join" type queries. 

Customers.SelectMany (
   c => c.Orders.DefaultIfEmpty (), 
   (c, o) => new  
   {
      CustomerID = c.CustomerID, 
      CompanyName = c.CompanyName, 
      oid = ((Int32?)(o.OrderID) == null) ? 0 : o.OrderID, 
      OrderDate = o.OrderDate
   }
)

It supports a parameter of TSource defining "empty" value. Here is a sample from MSDN documentation:

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static void DefaultIfEmptyEx2()
{
    Pet defaultPet = new Pet { Name = "Default Pet", Age = 0 };

    List<Pet> pets1 =
        new List<Pet>{ new Pet { Name="Barley", Age=8 },
                       new Pet { Name="Boots", Age=4 },
                       new Pet { Name="Whiskers", Age=1 } };

    foreach (Pet pet in pets1.DefaultIfEmpty(defaultPet))
    {
        Console.WriteLine("Name: {0}", pet.Name);
    }

    List<Pet> pets2 = new List<Pet>();

    foreach (Pet pet in pets2.DefaultIfEmpty(defaultPet))
    {
        Console.WriteLine("\nName: {0}", pet.Name);
    }
}

/*
This code produces the following output:

Name: Barley
Name: Boots
Name: Whiskers

Name: Default Pet
*/

Advertisements

About cetinbasoz

A developer working primarily with C#,F#,VFP,SQL server, Silverlight,Linq ...
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s