EditChapter 4 - Grouping and Sorting
EditGrouping
EditListing 4-1 : Simple grouping
This sample demonstrates grouping, and then working with each group.
public void Listing_4_1_Simple_Grouping()
{
string[] partNumbers = new string[] { "SCW10", "SCW1",
"SCW2", "SCW11", "NUT10", "NUT1", "NUT2", "NUT11" };
var q = from pn in partNumbers
group pn by pn.Substring(0, 3);
foreach (var group in q)
{
Console.WriteLine("Group key: {0}", group.Key);
foreach (var part in group)
Console.WriteLine(" – {0}", part);
}
}
Console output (Execution time: 3ms):
[
Hide/Show]
Group key: SCW
– SCW10
– SCW1
– SCW2
– SCW11
Group key: NUT
– NUT10
– NUT1
– NUT2
– NUT11
Top
EditListing 4-2 : Handling null values using the null-coalescing-operator (??) and the ternary operator (?).
This sample demonstrates how to handle null values in the selector expression when grouping
public void Listing_4_2_Handling_Nulls_WithNCOAndTernary()
{
// Guard against null data using
// ternary (? as shown)
var q1 = from c in Contact.SampleData()
group c by
c.State == null ? "(null)" : c.State;
// Guard against null data using
// the null coalescing operator (??).
var q2 = from c in Contact.SampleData()
group c by
c.State ?? "(null)";
}
Top
EditListing 4 : Handling null values
This sample demonstrates how to handle null values in the selector expression when grouping
public void Listing_4_Handling_Nulls()
{
string[] partNumbers = new string[] { "SCW10", null,
"SCW2", "SCW11", null, "NUT1", "NUT2", null };
// Advice – Guard against null data using ternary
// (? as shown) or the null coalescing operator (??).
var q1 = from pn in partNumbers
group pn by
pn == null ? "(null)" : pn.Substring(0,3);
Console.WriteLine("q1 result – ");
Console.WriteLine();
foreach (var group in q1)
{
// works as expected. All nulls grouped in "(null)"
Console.WriteLine("Group key: {0}", group.Key);
foreach (var part in group)
Console.WriteLine(" – {0}", part);
}
// Beware – nulls in source data can break your group
// expression. This grouping will fail.
var q2 = from pn in partNumbers
group pn by pn.Substring(0, 3);
Console.WriteLine();
Console.WriteLine("q2 result – Not handling nulls –");
Console.WriteLine();
foreach (var group in q2)
{
// fails with null exception!
}
}
Console output (Execution time: 19ms):
[
Hide/Show]
q1 result –
Group key: SCW
– SCW10
– SCW2
– SCW11
Group key: (null)
–
–
–
Group key: NUT
– NUT1
– NUT2
q2 result – Not handling nulls –
System.NullReferenceException: Object reference not set to an instance of an object.
at SampleQueries.Chapter04Samples.<Listing_4_Handling_Nulls>b__b(String pn) in C:\Users\Troy\Desktop\HOL Book\LINQ to Objects using CSharp 4 Samples\LINQ to Objects using CSharp 4 Sample Queries\Chapter04Samples.cs:line 196
at System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at System.Linq.GroupedEnumerable`3.GetEnumerator()
at SampleQueries.Chapter04Samples.Listing_4_Handling_Nulls() in C:\Users\Troy\Desktop\HOL Book\LINQ to Objects using CSharp 4 Samples\LINQ to Objects using CSharp 4 Sample Queries\Chapter04Samples.cs:line 201
Top
EditListing 4-3 : Grouping by multiple values
This sample demonstrates how to use anonymous types to group by more than one value.
public void Listing_4_3_Grouping_Multiple_Values()
{
/* This sample uses the same data as we saw in Table 2–2,
but i've added 2 Gottshall's (one from the same state
and another out of that state), and two Gauwain's –
Firstname Lastname State
–––––––––––––––––––––––––––––
Barney Gottshall CA
Mandy Gottshall CA
Bernadette Gottshall WA
Armando Valdes WA
Adam Gauwain AK
Chris Gauwain AK
Anthony Gauwain CA
Jeffery Deane CA
Collin Zeeman FL
Stewart Kagel WA
Chance Lard WA
Blaine Reifsteck TX
Mack Kamph TX
Ariel Hazelgrove OR
*/
var q = from c in Contact.SampleData()
group c by new { c.LastName, c.State };
foreach (var grp in q)
{
Console.WriteLine("Group – {0}, {1} – count = {2}",
grp.Key.LastName,
grp.Key.State,
grp.Count());
}
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Extension { get; set; }
public DateTime DateOfBirth { get; set; }
public string State { get; set; }
public static List<Contact> SampleData()
{
return new List<Contact> {
new Contact {FirstName = "Barney", LastName = "Gottshall", DateOfBirth = new DateTime(1945,10,19), Phone = "885 983 8858", Extension = "", Email = "bgottshall@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Mandy", LastName = "Gottshall", State = "CA" },
new Contact {FirstName = "Bernadette", LastName = "Gottshall", State = "WA" },
new Contact {FirstName = "Armando", LastName = "Valdes", DateOfBirth = new DateTime(1973,12,09), Phone = "848 553 8487", Extension = "", Email = "val1@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Adam", LastName = "Gauwain", DateOfBirth = new DateTime(1959,10,03), Phone = "115 999 1154", Extension = "", Email = "adamg@aspiring–technology.com", State = "AK" },
new Contact {FirstName = "Chris", LastName = "Gauwain", State = "AK" },
new Contact {FirstName = "Anthony", LastName = "Gauwain", State = "CA" },
new Contact {FirstName = "Jeffery", LastName = "Deane", DateOfBirth = new DateTime(1950,12,16), Phone = "677 602 6774", Extension = "", Email = "jeff.deane@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Collin", LastName = "Zeeman", DateOfBirth = new DateTime(1935,02,10), Phone = "603 303 6030", Extension = "", Email = "czeeman@aspiring–technology.com", State = "FL" },
new Contact {FirstName = "Stewart", LastName = "Kagel", DateOfBirth = new DateTime(1950,02,20), Phone = "546 607 5462", Extension = "", Email = "kagels@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Chance", LastName = "Lard", DateOfBirth = new DateTime(1951,10,21), Phone = "278 918 2789", Extension = "", Email = "lard@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Blaine", LastName = "Reifsteck", DateOfBirth = new DateTime(1946,05,18), Phone = "715 920 7157", Extension = "", Email = "blaine@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Mack", LastName = "Kamph", DateOfBirth = new DateTime(1977,09,17), Phone = "364 202 3644", Extension = "", Email = "mack.kamph@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Ariel", LastName = "Hazelgrove", DateOfBirth = new DateTime(1922,05,23), Phone = "165 737 1656", Extension = "", Email = "arielh@aspiring–technology.com", State = "OR" }
};
}
}
Console output (Execution time: 9ms):
[
Hide/Show]
Group – Gottshall, CA – count = 2
Group – Gottshall, WA – count = 1
Group – Valdes, WA – count = 1
Group – Gauwain, AK – count = 2
Group – Gauwain, CA – count = 1
Group – Deane, CA – count = 1
Group – Zeeman, FL – count = 1
Group – Kagel, WA – count = 1
Group – Lard, WA – count = 1
Group – Reifsteck, TX – count = 1
Group – Kamph, TX – count = 1
Group – Hazelgrove, OR – count = 1
Top
EditListing 4-4 : Grouping by multiple values
This sample demonstrates how to use a concrete to group by more than one value.
public void Listing_4_4_Grouping_Multiple_Values()
{
var q = from c in Contact.SampleData()
group c by new LastNameState {
LastName = c.LastName, State = c.State };
foreach (var grp in q)
{
Console.WriteLine("Group – {0}, {1} – count = {2}",
grp.Key.LastName,
grp.Key.State,
grp.Count());
}
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Extension { get; set; }
public DateTime DateOfBirth { get; set; }
public string State { get; set; }
public static List<Contact> SampleData()
{
return new List<Contact> {
new Contact {FirstName = "Barney", LastName = "Gottshall", DateOfBirth = new DateTime(1945,10,19), Phone = "885 983 8858", Extension = "", Email = "bgottshall@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Mandy", LastName = "Gottshall", State = "CA" },
new Contact {FirstName = "Bernadette", LastName = "Gottshall", State = "WA" },
new Contact {FirstName = "Armando", LastName = "Valdes", DateOfBirth = new DateTime(1973,12,09), Phone = "848 553 8487", Extension = "", Email = "val1@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Adam", LastName = "Gauwain", DateOfBirth = new DateTime(1959,10,03), Phone = "115 999 1154", Extension = "", Email = "adamg@aspiring–technology.com", State = "AK" },
new Contact {FirstName = "Chris", LastName = "Gauwain", State = "AK" },
new Contact {FirstName = "Anthony", LastName = "Gauwain", State = "CA" },
new Contact {FirstName = "Jeffery", LastName = "Deane", DateOfBirth = new DateTime(1950,12,16), Phone = "677 602 6774", Extension = "", Email = "jeff.deane@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Collin", LastName = "Zeeman", DateOfBirth = new DateTime(1935,02,10), Phone = "603 303 6030", Extension = "", Email = "czeeman@aspiring–technology.com", State = "FL" },
new Contact {FirstName = "Stewart", LastName = "Kagel", DateOfBirth = new DateTime(1950,02,20), Phone = "546 607 5462", Extension = "", Email = "kagels@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Chance", LastName = "Lard", DateOfBirth = new DateTime(1951,10,21), Phone = "278 918 2789", Extension = "", Email = "lard@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Blaine", LastName = "Reifsteck", DateOfBirth = new DateTime(1946,05,18), Phone = "715 920 7157", Extension = "", Email = "blaine@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Mack", LastName = "Kamph", DateOfBirth = new DateTime(1977,09,17), Phone = "364 202 3644", Extension = "", Email = "mack.kamph@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Ariel", LastName = "Hazelgrove", DateOfBirth = new DateTime(1922,05,23), Phone = "165 737 1656", Extension = "", Email = "arielh@aspiring–technology.com", State = "OR" }
};
}
}
public class LastNameState
{
public string LastName { get; set; }
public string State { get; set; }
// follow the MSDN guidelines –
// http://msdn.microsoft.com/en–us/library/
// ms173147(VS.80).aspx
public override bool Equals(object obj)
{
if (this != obj)
{
LastNameState item = obj as LastNameState;
if (item == null) return false;
if (State != item.State) return false;
if (LastName != item.LastName) return false;
}
return true;
}
// follow the MSDN guidelines –
// http://msdn.microsoft.com/en–us/library/
// system.object.gethashcode.aspx
public override int GetHashCode()
{
int result = State != null ? State.GetHashCode() : 1;
result = result ^
(LastName != null ? LastName.GetHashCode() : 2);
return result;
}
}
Console output (Execution time: 6ms):
[
Hide/Show]
Group – Gottshall, CA – count = 2
Group – Gottshall, WA – count = 1
Group – Valdes, WA – count = 1
Group – Gauwain, AK – count = 2
Group – Gauwain, CA – count = 1
Group – Deane, CA – count = 1
Group – Zeeman, FL – count = 1
Group – Kagel, WA – count = 1
Group – Lard, WA – count = 1
Group – Reifsteck, TX – count = 1
Group – Kamph, TX – count = 1
Group – Hazelgrove, OR – count = 1
Top
EditListing 4-5 : Soundex Custom Equality Comparer
This sample demonstrates how to construct a custom equality comparer. The sample builds a Soundex comparer.
public void Listing_4_5_Soundex()
{
// example just to show the code for the Soundex Equality Comparer.
}
public class SoundexEqualityComparer
: IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return GetHashCode(x) == GetHashCode(y);
}
public int GetHashCode(string obj)
{
// E.g. convert soundex code A123,
// to an integer: 65123
int result = 0;
string s = soundex(obj);
if (string.IsNullOrEmpty(s) == false)
result = Convert.ToInt32(s[0]) * 1000 +
Convert.ToInt32(s.Substring(1, 3));
return result;
}
private string soundex(string s)
{
// Algorithm as listed on
// http://en.wikipedia.org/wiki/Soundex.
// builds a string code in the format:
// A–Z0–60–60–6
// based on the phonetic sound of the input.
if (String.IsNullOrEmpty(s))
return null;
StringBuilder result =
new StringBuilder();
string source = s.ToUpper().Replace(" ", "");
// add the first character, then loop the
// string mapping as we go
result.Append(source[0]);
char previous = '0';
for (int i = 1; i < source.Length; i++)
{
// map to the soundex numeral
char mappedTo = '0';
char thisChar = source[i];
if ("BFPV".Contains(thisChar))
mappedTo = '1';
else if ("CGJKQSXZ".Contains(thisChar))
mappedTo = '2';
else if ("DT".Contains(thisChar))
mappedTo = '3';
else if ('L' == thisChar)
mappedTo = '4';
else if ("MN".Contains(thisChar))
mappedTo = '5';
else if ('R' == thisChar)
mappedTo = '6';
// ignore adjacent duplicates and
// non–matched characters
if (mappedTo != previous && mappedTo != '0')
{
result.Append(mappedTo);
previous = mappedTo;
}
}
while (result.Length < 4)
result.Append("0");
return result.ToString(0, 4);
}
}
Top
EditListing 4-6 : Custom Equality Comparer
This sample demonstrates how to use a custom equality comparer.
public void Listing_4_6_Cuatom_Equality_Comparer()
{
string[] names = new string[] { "Janet", "Janette", "Joanne",
"Jo–anne", "Johanne", "Katy", "Katie", "Ralph", "Ralphe" };
var q = names.GroupBy(s => s,
new SoundexEqualityComparer());
foreach (var group in q)
{
Console.WriteLine(group.Key);
foreach (var name in group)
Console.WriteLine(" – {0}", name);
}
}
public class SoundexEqualityComparer
: IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return GetHashCode(x) == GetHashCode(y);
}
public int GetHashCode(string obj)
{
// E.g. convert soundex code A123,
// to an integer: 65123
int result = 0;
string s = soundex(obj);
if (string.IsNullOrEmpty(s) == false)
result = Convert.ToInt32(s[0]) * 1000 +
Convert.ToInt32(s.Substring(1, 3));
return result;
}
private string soundex(string s)
{
// Algorithm as listed on
// http://en.wikipedia.org/wiki/Soundex.
// builds a string code in the format:
// A–Z0–60–60–6
// based on the phonetic sound of the input.
if (String.IsNullOrEmpty(s))
return null;
StringBuilder result =
new StringBuilder();
string source = s.ToUpper().Replace(" ", "");
// add the first character, then loop the
// string mapping as we go
result.Append(source[0]);
char previous = '0';
for (int i = 1; i < source.Length; i++)
{
// map to the soundex numeral
char mappedTo = '0';
char thisChar = source[i];
if ("BFPV".Contains(thisChar))
mappedTo = '1';
else if ("CGJKQSXZ".Contains(thisChar))
mappedTo = '2';
else if ("DT".Contains(thisChar))
mappedTo = '3';
else if ('L' == thisChar)
mappedTo = '4';
else if ("MN".Contains(thisChar))
mappedTo = '5';
else if ('R' == thisChar)
mappedTo = '6';
// ignore adjacent duplicates and
// non–matched characters
if (mappedTo != previous && mappedTo != '0')
{
result.Append(mappedTo);
previous = mappedTo;
}
}
while (result.Length < 4)
result.Append("0");
return result.ToString(0, 4);
}
}
Console output (Execution time: 8ms):
[
Hide/Show]
Janet
– Janet
– Janette
Joanne
– Joanne
– Jo–anne
– Johanne
Katy
– Katy
– Katie
Ralph
– Ralph
– Ralphe
Top
EditListing 4-7 : Custom element projection into group.
This sample demonstrates how to change the element projection into each grouping.
public void Listing_4_7_Cuatom_Element_Projection()
{
IList<Contact> contacts = Contact.SampleData();
var q = contacts.GroupBy(
c => c.State,
c => c.FirstName + " " + c.LastName);
foreach (var group in q)
{
Console.WriteLine("State: {0}", group.Key);
foreach (string name in group)
Console.WriteLine(" {0}", name);
}
}
Console output (Execution time: 2ms):
[
Hide/Show]
State: CA
Barney Gottshall
Mandy Gottshall
Anthony Gauwain
Jeffery Deane
State: WA
Bernadette Gottshall
Armando Valdes
Stewart Kagel
Chance Lard
State: AK
Adam Gauwain
Chris Gauwain
State: FL
Collin Zeeman
State: TX
Blaine Reifsteck
Mack Kamph
State: OR
Ariel Hazelgrove
Top
EditListing 4-8 : Custom element projection into group.
This sample demonstrates how to change the element projection into each grouping.
public void Listing_4_8_Custom_Element_Projection_AnonymousType()
{
List<Contact> contacts = Contact.SampleData();
var q = contacts.GroupBy(
c => c.State ?? "state unknown",
c => new
{
Title = c.FirstName + " " + c.LastName,
Email = c.Email ?? "email address unknown"
});
foreach (var group in q)
{
Console.WriteLine("State: {0}", group.Key);
foreach (var element in group)
Console.WriteLine(" {0} ({1})",
element.Title,
element.Email);
}
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Extension { get; set; }
public DateTime DateOfBirth { get; set; }
public string State { get; set; }
public static List<Contact> SampleData()
{
return new List<Contact> {
new Contact {FirstName = "Barney", LastName = "Gottshall", DateOfBirth = new DateTime(1945,10,19), Phone = "885 983 8858", Extension = "", Email = "bgottshall@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Mandy", LastName = "Gottshall", State = "CA" },
new Contact {FirstName = "Bernadette", LastName = "Gottshall", State = "WA" },
new Contact {FirstName = "Armando", LastName = "Valdes", DateOfBirth = new DateTime(1973,12,09), Phone = "848 553 8487", Extension = "", Email = "val1@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Adam", LastName = "Gauwain", DateOfBirth = new DateTime(1959,10,03), Phone = "115 999 1154", Extension = "", Email = "adamg@aspiring–technology.com", State = "AK" },
new Contact {FirstName = "Chris", LastName = "Gauwain", State = "AK" },
new Contact {FirstName = "Anthony", LastName = "Gauwain", State = "CA" },
new Contact {FirstName = "Jeffery", LastName = "Deane", DateOfBirth = new DateTime(1950,12,16), Phone = "677 602 6774", Extension = "", Email = "jeff.deane@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Collin", LastName = "Zeeman", DateOfBirth = new DateTime(1935,02,10), Phone = "603 303 6030", Extension = "", Email = "czeeman@aspiring–technology.com", State = "FL" },
new Contact {FirstName = "Stewart", LastName = "Kagel", DateOfBirth = new DateTime(1950,02,20), Phone = "546 607 5462", Extension = "", Email = "kagels@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Chance", LastName = "Lard", DateOfBirth = new DateTime(1951,10,21), Phone = "278 918 2789", Extension = "", Email = "lard@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Blaine", LastName = "Reifsteck", DateOfBirth = new DateTime(1946,05,18), Phone = "715 920 7157", Extension = "", Email = "blaine@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Mack", LastName = "Kamph", DateOfBirth = new DateTime(1977,09,17), Phone = "364 202 3644", Extension = "", Email = "mack.kamph@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Ariel", LastName = "Hazelgrove", DateOfBirth = new DateTime(1922,05,23), Phone = "165 737 1656", Extension = "", Email = "arielh@aspiring–technology.com", State = "OR" }
};
}
}
Console output (Execution time: 6ms):
[
Hide/Show]
State: CA
Barney Gottshall (bgottshall@aspiring–technology.com)
Mandy Gottshall (email address unknown)
Anthony Gauwain (email address unknown)
Jeffery Deane (jeff.deane@aspiring–technology.com)
State: WA
Bernadette Gottshall (email address unknown)
Armando Valdes (val1@aspiring–technology.com)
Stewart Kagel (kagels@aspiring–technology.com)
Chance Lard (lard@aspiring–technology.com)
State: AK
Adam Gauwain (adamg@aspiring–technology.com)
Chris Gauwain (email address unknown)
State: FL
Collin Zeeman (czeeman@aspiring–technology.com)
State: TX
Blaine Reifsteck (blaine@aspiring–technology.com)
Mack Kamph (mack.kamph@aspiring–technology.com)
State: OR
Ariel Hazelgrove (arielh@aspiring–technology.com)
Top
EditListing 4-9 : Grouping Query Continuation and Aggregation.
This sample demonstrates how to use grouping results in the same query and extract aggregate values.
public void Listing_4_9_Grouping_Query_Continuation()
{
List<CallLog> calls = CallLog.SampleData();
var q = from c in calls
group c by c.Number into g
select new
{
Number = g.Key,
InCalls = g.Count(c => c.Incoming),
OutCalls = g.Count(c => !c.Incoming),
TotalTime = g.Sum(c => c.Duration),
AvgTime = g.Average(c => c.Duration)
};
foreach (var number in q)
Console.WriteLine(
"{0} ({1} in, {2} out) Avg Time: {3} mins",
number.Number,
number.InCalls,
number.OutCalls,
Math.Round(number.AvgTime, 2));
}
public class CallLog
{
public string Number { get; set; }
public int Duration { get; set; }
public bool Incoming { get; set; }
public DateTime When { get; set; }
public string Extension { get; set; }
public static List<CallLog> SampleData()
{
return new List<CallLog> {
new CallLog { Number = "885 983 8858", Extension = "", Duration = 2, Incoming = true, When = new DateTime(2006, 8, 7, 8, 12, 0)},
new CallLog { Number = "165 737 1656", Extension = "", Duration = 15, Incoming = true, When = new DateTime(2006, 8, 7, 9, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 1, Incoming = false, When = new DateTime(2006, 8, 7, 10, 5, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 2, Incoming = false, When = new DateTime(2006, 8, 7, 10, 35, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 4, Incoming = true, When = new DateTime(2006, 8, 7, 11, 15, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 15, Incoming = false, When = new DateTime(2006, 8, 7, 13, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 3, Incoming = true, When = new DateTime(2006, 8, 7, 13, 47, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 1, Incoming = false, When = new DateTime(2006, 8, 7, 20, 34, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 8, 8, 10, 10, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 23, Incoming = false, When = new DateTime(2006, 8, 8, 10, 40, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 8, 8, 14, 0, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 7, Incoming = true, When = new DateTime(2006, 8, 8, 14, 37, 0) },
new CallLog { Number = "278 918 2789", Extension = "", Duration = 6, Incoming = true, When = new DateTime(2006, 8, 8, 15, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 20, Incoming = true, When = new DateTime(2006, 8, 8, 17, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 5, Incoming = true, When = new DateTime(2006, 7, 12, 8, 12, 0)},
new CallLog { Number = "165 737 1656", Extension = "", Duration = 12, Incoming = true, When = new DateTime(2006, 6, 14, 9, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 10, Incoming = false, When = new DateTime(2006, 7, 9, 10, 5, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 22, Incoming = false, When = new DateTime(2006, 7, 5, 10, 35, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 9, Incoming = true, When = new DateTime(2006, 6, 7, 11, 15, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 10, Incoming = false, When = new DateTime(2006, 6, 7, 13, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 21, Incoming = true, When = new DateTime(2006, 7, 7, 13, 47, 0) },
new CallLog { Number = "546 607 5462", Extension = "",Duration = 7, Incoming = false, When = new DateTime(2006, 7, 7, 20, 34, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 2, Incoming = false, When = new DateTime(2006, 6, 8, 10, 10, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 6, 8, 10, 40, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 32, Incoming = false, When = new DateTime(2006, 7, 8, 14, 0, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 13, Incoming = true, When = new DateTime(2006, 7, 8, 14, 37, 0) },
new CallLog { Number = "278 918 2789", Extension = "", Duration = 16, Incoming = true, When = new DateTime(2006, 5, 8, 15, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 24, Incoming = true, When = new DateTime(2006, 6, 8, 17, 12, 0) }
};
}
}
Console output (Execution time: 13ms):
[
Hide/Show]
885 983 8858 (4 in, 2 out) Avg Time: 9.33 mins
165 737 1656 (2 in, 0 out) Avg Time: 13.5 mins
364 202 3644 (2 in, 2 out) Avg Time: 13.75 mins
603 303 6030 (0 in, 4 out) Avg Time: 12.5 mins
546 607 5462 (2 in, 4 out) Avg Time: 4.33 mins
848 553 8487 (2 in, 2 out) Avg Time: 13.75 mins
278 918 2789 (2 in, 0 out) Avg Time: 11 mins
Top
EditListing 4-10 : Nested Grouping Query Continuation.
This sample demonstrates how to nest and aggregate grouped data.
public void Listing_4_10_Nested_Grouping_Query_Continuation()
{
List<Contact> contacts = Contact.SampleData();
List<CallLog> callLog = CallLog.SampleData();
var q = from contact in contacts
select new
{
Name = contact.FirstName + " " +
contact.LastName,
YearGroup = from call in callLog
where call.Number == contact.Phone
group call by call.When.Year
into groupYear
select new
{
Year = groupYear.Key,
MonthGroup =
from c in groupYear
group c by c.When.ToString("MMMM")
}
};
foreach (var con in q)
{
Console.WriteLine("Customer: {0}", con.Name);
foreach (var year in con.YearGroup)
{
Console.WriteLine(" Year:{0}", year.Year);
foreach (var month in year.MonthGroup)
{
Console.WriteLine(" Month:{0}", month.Key);
foreach (var call in month)
{
Console.WriteLine(" {0} – for {1} minutes",
call.When, call.Duration);
}
}
}
}
}
public class CallLog
{
public string Number { get; set; }
public int Duration { get; set; }
public bool Incoming { get; set; }
public DateTime When { get; set; }
public string Extension { get; set; }
public static List<CallLog> SampleData()
{
return new List<CallLog> {
new CallLog { Number = "885 983 8858", Extension = "", Duration = 2, Incoming = true, When = new DateTime(2006, 8, 7, 8, 12, 0)},
new CallLog { Number = "165 737 1656", Extension = "", Duration = 15, Incoming = true, When = new DateTime(2006, 8, 7, 9, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 1, Incoming = false, When = new DateTime(2006, 8, 7, 10, 5, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 2, Incoming = false, When = new DateTime(2006, 8, 7, 10, 35, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 4, Incoming = true, When = new DateTime(2006, 8, 7, 11, 15, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 15, Incoming = false, When = new DateTime(2006, 8, 7, 13, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 3, Incoming = true, When = new DateTime(2006, 8, 7, 13, 47, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 1, Incoming = false, When = new DateTime(2006, 8, 7, 20, 34, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 8, 8, 10, 10, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 23, Incoming = false, When = new DateTime(2006, 8, 8, 10, 40, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 8, 8, 14, 0, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 7, Incoming = true, When = new DateTime(2006, 8, 8, 14, 37, 0) },
new CallLog { Number = "278 918 2789", Extension = "", Duration = 6, Incoming = true, When = new DateTime(2006, 8, 8, 15, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 20, Incoming = true, When = new DateTime(2006, 8, 8, 17, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 5, Incoming = true, When = new DateTime(2006, 7, 12, 8, 12, 0)},
new CallLog { Number = "165 737 1656", Extension = "", Duration = 12, Incoming = true, When = new DateTime(2006, 6, 14, 9, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 10, Incoming = false, When = new DateTime(2006, 7, 9, 10, 5, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 22, Incoming = false, When = new DateTime(2006, 7, 5, 10, 35, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 9, Incoming = true, When = new DateTime(2006, 6, 7, 11, 15, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 10, Incoming = false, When = new DateTime(2006, 6, 7, 13, 12, 0) },
new CallLog { Number = "885 983 8858", Extension = "", Duration = 21, Incoming = true, When = new DateTime(2006, 7, 7, 13, 47, 0) },
new CallLog { Number = "546 607 5462", Extension = "",Duration = 7, Incoming = false, When = new DateTime(2006, 7, 7, 20, 34, 0) },
new CallLog { Number = "546 607 5462", Extension = "", Duration = 2, Incoming = false, When = new DateTime(2006, 6, 8, 10, 10, 0) },
new CallLog { Number = "603 303 6030", Extension = "", Duration = 3, Incoming = false, When = new DateTime(2006, 6, 8, 10, 40, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 32, Incoming = false, When = new DateTime(2006, 7, 8, 14, 0, 0) },
new CallLog { Number = "848 553 8487", Extension = "", Duration = 13, Incoming = true, When = new DateTime(2006, 7, 8, 14, 37, 0) },
new CallLog { Number = "278 918 2789", Extension = "", Duration = 16, Incoming = true, When = new DateTime(2006, 5, 8, 15, 23, 0) },
new CallLog { Number = "364 202 3644", Extension = "", Duration = 24, Incoming = true, When = new DateTime(2006, 6, 8, 17, 12, 0) }
};
}
}
public class Contact
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Extension { get; set; }
public DateTime DateOfBirth { get; set; }
public string State { get; set; }
public static List<Contact> SampleData()
{
return new List<Contact> {
new Contact {FirstName = "Barney", LastName = "Gottshall", DateOfBirth = new DateTime(1945,10,19), Phone = "885 983 8858", Extension = "", Email = "bgottshall@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Mandy", LastName = "Gottshall", State = "CA" },
new Contact {FirstName = "Bernadette", LastName = "Gottshall", State = "WA" },
new Contact {FirstName = "Armando", LastName = "Valdes", DateOfBirth = new DateTime(1973,12,09), Phone = "848 553 8487", Extension = "", Email = "val1@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Adam", LastName = "Gauwain", DateOfBirth = new DateTime(1959,10,03), Phone = "115 999 1154", Extension = "", Email = "adamg@aspiring–technology.com", State = "AK" },
new Contact {FirstName = "Chris", LastName = "Gauwain", State = "AK" },
new Contact {FirstName = "Anthony", LastName = "Gauwain", State = "CA" },
new Contact {FirstName = "Jeffery", LastName = "Deane", DateOfBirth = new DateTime(1950,12,16), Phone = "677 602 6774", Extension = "", Email = "jeff.deane@aspiring–technology.com", State = "CA" },
new Contact {FirstName = "Collin", LastName = "Zeeman", DateOfBirth = new DateTime(1935,02,10), Phone = "603 303 6030", Extension = "", Email = "czeeman@aspiring–technology.com", State = "FL" },
new Contact {FirstName = "Stewart", LastName = "Kagel", DateOfBirth = new DateTime(1950,02,20), Phone = "546 607 5462", Extension = "", Email = "kagels@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Chance", LastName = "Lard", DateOfBirth = new DateTime(1951,10,21), Phone = "278 918 2789", Extension = "", Email = "lard@aspiring–technology.com", State = "WA" },
new Contact {FirstName = "Blaine", LastName = "Reifsteck", DateOfBirth = new DateTime(1946,05,18), Phone = "715 920 7157", Extension = "", Email = "blaine@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Mack", LastName = "Kamph", DateOfBirth = new DateTime(1977,09,17), Phone = "364 202 3644", Extension = "", Email = "mack.kamph@aspiring–technology.com", State = "TX" },
new Contact {FirstName = "Ariel", LastName = "Hazelgrove", DateOfBirth = new DateTime(1922,05,23), Phone = "165 737 1656", Extension = "", Email = "arielh@aspiring–technology.com", State = "OR" }
};
}
}
Console output (Execution time: 16ms):
[
Hide/Show]
Customer: Barney Gottshall
Year:2006
Month:August
8/7/2006 8:12:00 AM – for 2 minutes
8/7/2006 1:12:00 PM – for 15 minutes
8/7/2006 1:47:00 PM – for 3 minutes
Month:July
7/12/2006 8:12:00 AM – for 5 minutes
7/7/2006 1:47:00 PM – for 21 minutes
Month:June
6/7/2006 1:12:00 PM – for 10 minutes
Customer: Mandy Gottshall
Customer: Bernadette Gottshall
Customer: Armando Valdes
Year:2006
Month:August
8/8/2006 2:00:00 PM – for 3 minutes
8/8/2006 2:37:00 PM – for 7 minutes
Month:July
7/8/2006 2:00:00 PM – for 32 minutes
7/8/2006 2:37:00 PM – for 13 minutes
Customer: Adam Gauwain
Customer: Chris Gauwain
Customer: Anthony Gauwain
Customer: Jeffery Deane
Customer: Collin Zeeman
Year:2006
Month:August
8/7/2006 10:35:00 AM – for 2 minutes
8/8/2006 10:40:00 AM – for 23 minutes
Month:July
7/5/2006 10:35:00 AM – for 22 minutes
Month:June
6/8/2006 10:40:00 AM – for 3 minutes
Customer: Stewart Kagel
Year:2006
Month:August
8/7/2006 11:15:00 AM – for 4 minutes
8/7/2006 8:34:00 PM – for 1 minutes
8/8/2006 10:10:00 AM – for 3 minutes
Month:June
6/7/2006 11:15:00 AM – for 9 minutes
6/8/2006 10:10:00 AM – for 2 minutes
Month:July
7/7/2006 8:34:00 PM – for 7 minutes
Customer: Chance Lard
Year:2006
Month:August
8/8/2006 3:23:00 PM – for 6 minutes
Month:May
5/8/2006 3:23:00 PM – for 16 minutes
Customer: Blaine Reifsteck
Customer: Mack Kamph
Year:2006
Month:August
8/7/2006 10:05:00 AM – for 1 minutes
8/8/2006 5:12:00 PM – for 20 minutes
Month:July
7/9/2006 10:05:00 AM – for 10 minutes
Month:June
6/8/2006 5:12:00 PM – for 24 minutes
Customer: Ariel Hazelgrove
Year:2006
Month:August
8/7/2006 9:23:00 AM – for 15 minutes
Month:June
6/14/2006 9:23:00 AM – for 12 minutes
Top
EditJoining
EditListing 4 : Cross-Join example.
This sample demonstrates a simple cross-join.
public void Listing_4_Cross_Join()
{
var outer = Enumerable.Range(1, 3);
var inner = Enumerable.Range(1, 3);
// query Expression syntax
var q = from x in outer
from y in inner
select new { x, y };
foreach (var element in q)
Console.WriteLine("{0}, {1}", element.x, element.y);
// extension Method syntax
var q1 = outer
.SelectMany(
x => inner, // inner collection selector
(x, y) => new { x, y } // select projection
);
Console.WriteLine();
foreach (var element in q1)
Console.WriteLine("{0}, {1}", element.x, element.y);
}
Console output (Execution time: 8ms):
[
Hide/Show]
1, 1
1, 2
1, 3
2, 1
2, 2
2, 3
3, 1
3, 2
3, 3
1, 1
1, 2
1, 3
2, 1
2, 2
2, 3
3, 1
3, 2
3, 3
Top
EditListing 4-11 : Cross-Join binary sequence example.
This sample demonstrates a cross-join that build all combinations of a 4-bit binary sequence.
public void Listing_4_11_Cross_Join_BinaryExample()
{
var binary = new int[] { 0, 1 };
var q = from b4 in binary
from b3 in binary
from b2 in binary
from b1 in binary
select String.Format(
"{0}{1}{2}{3}", b4, b3, b2, b1);
foreach (var element in q)
Console.WriteLine(element);
}
Console output (Execution time: 8ms):
[
Hide/Show]
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Top
EditListing 4 : Cross-Join bitmap sequence.
This sample demonstrates a cross-join that accesses each pixel in a bitmap.
public void Listing_4_Cross_Join_BitmapExample()
{
Bitmap bm = new Bitmap(5,5);
var q = from x in Enumerable.Range(0, bm.Width)
from y in Enumerable.Range(0, bm.Height)
select bm.GetPixel(x, y);
foreach (var element in q)
Console.WriteLine(element);
}
Console output (Execution time: 4ms):
[
Hide/Show]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Color [A=0, R=0, G=0, B=0]
Top
EditListing 4 : Simple Join example.
This sample demonstrates a simple inner-join between two string arrays.
public void Listing_4_Simple_Join()
{
string[] outer = new string[] { "a", "b", "c", "d" };
string[] inner = new string[] { "b", "c", "d", "e" };
var q = from s1 in outer
join s2 in inner on s1 equals s2
select string.Format(
"Outer: {0} Inner: {1}", s1, s2);
foreach (string s in q)
Console.WriteLine(s);
}
Console output (Execution time: 1ms):
[
Hide/Show]
Outer: b Inner: b
Outer: c Inner: c
Outer: d Inner: d
Top
EditListing 4-12 : One-one join using Join syntax.
This sample demonstrates a one-one join using the join Query Expression syntax.
public void Listing_4_12_One_to_One_JoinSyntax()
{
// scenario: You have an order number,
// and need the customer details.
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q1 = from o in orders
join c in customers on
o.CustomerID equals c.CustomerID
select new
{
o.OrderNumber,
c.LastName
};
foreach (var order in q1)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
Console output (Execution time: 4ms):
[
Hide/Show]
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4-13 : One-one outer-join using the Join syntax.
This sample demonstrates a one-one outer-join using the join Query Expression syntax.
public void Listing_4_13_One_to_One_OuterJoinSyntax()
{
// scenario: You have an order number,
// and need the customer details.
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q = from c in customers
join o in orders on
c.CustomerID equals o.CustomerID into j
from order in j.DefaultIfEmpty()
select new
{
LastName = c.LastName,
Order = order
};
foreach (var element in q)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
element.LastName.PadRight(9, ' '),
element.Order == null ?
"(no orders)" : element.Order.OrderNumber);
/* alternative, move null handling to select projection */
var q1 = from c in customers
join o in orders on
c.CustomerID equals o.CustomerID into j
from order in j.DefaultIfEmpty()
select new
{
LastName = c.LastName,
OrderNumber = order == null ?
"(no order)" : order.OrderNumber
};
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
Console output (Execution time: 5ms):
[
Hide/Show]
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Valdes Order Number: (no orders)
Customer: Gauwain Order Number: (no orders)
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4 : Composite-key join example.
This sample demonstrates a composite-key join.
public void Listing_4_CompositeKey_Join()
{
List<Contact> outer = Contact.SampleData();
List<CallLog> inner = CallLog.SampleData();
var q = from contact in outer
join call in inner on
new {
phone = contact.Phone,
contact.Extension
}
equals
new {
phone = call.Number,
call.Extension
}
select new { call, contact };
foreach (var e in q)
Console.WriteLine(
"{0}, {1}, {2}",
e.call.When, e.call.Number, e.contact.LastName);
}
Console output (Execution time: 4ms):
[
Hide/Show]
8/7/2006 8:12:00 AM, 885 983 8858, Gottshall
8/7/2006 1:12:00 PM, 885 983 8858, Gottshall
8/7/2006 1:47:00 PM, 885 983 8858, Gottshall
7/12/2006 8:12:00 AM, 885 983 8858, Gottshall
6/7/2006 1:12:00 PM, 885 983 8858, Gottshall
7/7/2006 1:47:00 PM, 885 983 8858, Gottshall
8/8/2006 2:00:00 PM, 848 553 8487, Valdes
8/8/2006 2:37:00 PM, 848 553 8487, Valdes
7/8/2006 2:00:00 PM, 848 553 8487, Valdes
7/8/2006 2:37:00 PM, 848 553 8487, Valdes
8/7/2006 10:35:00 AM, 603 303 6030, Zeeman
8/8/2006 10:40:00 AM, 603 303 6030, Zeeman
7/5/2006 10:35:00 AM, 603 303 6030, Zeeman
6/8/2006 10:40:00 AM, 603 303 6030, Zeeman
8/7/2006 11:15:00 AM, 546 607 5462, Kagel
8/7/2006 8:34:00 PM, 546 607 5462, Kagel
8/8/2006 10:10:00 AM, 546 607 5462, Kagel
6/7/2006 11:15:00 AM, 546 607 5462, Kagel
7/7/2006 8:34:00 PM, 546 607 5462, Kagel
6/8/2006 10:10:00 AM, 546 607 5462, Kagel
8/8/2006 3:23:00 PM, 278 918 2789, Lard
5/8/2006 3:23:00 PM, 278 918 2789, Lard
8/7/2006 10:05:00 AM, 364 202 3644, Kamph
8/8/2006 5:12:00 PM, 364 202 3644, Kamph
7/9/2006 10:05:00 AM, 364 202 3644, Kamph
6/8/2006 5:12:00 PM, 364 202 3644, Kamph
8/7/2006 9:23:00 AM, 165 737 1656, Hazelgrove
6/14/2006 9:23:00 AM, 165 737 1656, Hazelgrove
Top
EditListing 4-14 : One-one join using Sub-Query syntax.
This sample demonstrates a one-one join using the Sub-Query syntax.
public void Listing_4_14_One_to_One_SubQuerySyntax()
{
// scenario: You have an order number,
// and need the customer details.
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q2 = from o in orders
select new
{
OrderNumber = o.OrderNumber,
LastName = (from c in customers
where c.CustomerID == o.CustomerID
select c.LastName).SingleOrDefault()
};
foreach (var order in q2)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 2ms):
[
Hide/Show]
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4-15 : One-one join using SingleOrDefault syntax.
This sample demonstrates a one-one join using the SingleOrDefault syntax.
public void Listing_4_15_One_to_One_SingleOrDefaultSyntax()
{
// scenario: You have an order number,
// and need the customer details.
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q3 = from o in orders
let cust = customers
.SingleOrDefault(
c => c.CustomerID == o.CustomerID)
select new
{
OrderNumber = o.OrderNumber,
LastName = cust.LastName
};
foreach (var order in q3)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 2ms):
[
Hide/Show]
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4-16 : One-one join using cross-join/where syntax.
This sample demonstrates a one-one join using the Cross-join/where syntax.
public void Listing_4_16_One_to_One_CrossJoinSyntax()
{
// scenario: You have an order number,
// and need the customer details.
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q4 = from o in orders
from c in customers
where c.CustomerID == o.CustomerID
select new
{
o.OrderNumber,
c.LastName
};
foreach (var order in q4)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 3ms):
[
Hide/Show]
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4-12,14,15,16 : One-one joins two collections.
This sample demonstrates the different ways to achieve one-one joins between two collections.
public void Listing_4_One_to_One_Comparisons()
{
// comment out one of the two following lines for test
//var loopOuter = 19; // 100 outer records
var loopOuter = 9; // 50 records
//var loopOuter = 0; // 5 outer records
var customers = Customer.SampleData();
var orders = Order.SampleData();
for (int i = 0; i < loopOuter; i++)
orders = orders.Union(Order.SampleData()).ToList();
// You have an order number, and need the customer details
// join syntax
// fastest when looking up all order records
var q1 = from o in orders
//where o.OrderNumber == "Order 3"
join c in customers on
o.CustomerID equals c.CustomerID
select new
{
o.OrderNumber,
c.LastName
};
// sub–query syntax in select clause
// * not recommended *, use the SingleOrDefault operator
var q2 = from o in orders
//where o.OrderNumber == "Order 3"
select new
{
OrderNumber = o.OrderNumber,
LastName = (from c in customers
where c.CustomerID == o.CustomerID
select c.LastName).SingleOrDefault()
};
// sub–query syntax using SingleOrDefault operator
// fastest when looking up a single order record
var q3 = from o in orders
//where o.OrderNumber == "Order 3"
let cust = customers
.SingleOrDefault(
c => c.CustomerID == o.CustomerID)
select new
{
OrderNumber = o.OrderNumber,
LastName = cust.LastName
};
// cross–join / where syntax
// * not recommended *, use the Join syntax or sub–query
var q4 = from o in orders
//where o.OrderNumber == "Order 3"
from c in customers
where c.CustomerID == o.CustomerID
select new
{
o.OrderNumber,
c.LastName
};
Console.WriteLine("q1 = {0}ms, q2 = {1}ms, q3 = {2}ms, q4 = {3}ms",
MeasureTime(delegate { q1.ToList(); }, 1000000),
MeasureTime(delegate { q2.ToList(); }, 1000000),
MeasureTime(delegate { q3.ToList(); }, 1000000),
MeasureTime(delegate { q4.ToList(); }, 1000000)
);
Console.WriteLine(Environment.NewLine + "Join syntax:" );
foreach (var order in q1)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
Console.WriteLine(Environment.NewLine + "Sub–query syntax:");
foreach (var order in q2)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
Console.WriteLine(Environment.NewLine + "Sub–query / SingleOrDefault syntax:");
foreach (var order in q3)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
Console.WriteLine(Environment.NewLine + "Cross–Join / where syntax:");
foreach (var order in q4)
Console.WriteLine(
"Customer: {0} Order Number: {1}",
order.LastName.PadRight(9, ' '),
order.OrderNumber);
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 115765ms):
[
Hide/Show]
q1 = 10721ms, q2 = 36225ms, q3 = 26853ms, q4 = 41959ms
Join syntax:
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Sub–query syntax:
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Sub–query / SingleOrDefault syntax:
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Cross–Join / where syntax:
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Customer: Gottshall Order Number: Order 1
Customer: Gottshall Order Number: Order 2
Customer: Deane Order Number: Order 3
Customer: Deane Order Number: Order 4
Customer: Zeeman Order Number: Order 5
Top
EditListing 4-17 : One-many join using Join/Into syntax.
This sample demonstrates a one-many join using the join/into Query Expression syntax.
public void Listing_4_17_One_to_Many_JoinIntoSyntax()
{
// Scenario: You have a customer, and need the orders
// for that customer
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q1 = from c in customers
join o in orders on
c.CustomerID equals o.CustomerID
into cust_orders
select new
{
LastName = c.LastName,
Orders = cust_orders
};
foreach (var customer in q1)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
/* Extension method syntax */
var q1a = customers
.GroupJoin(
orders,
c => c.CustomerID,
o => o.CustomerID,
(c, o) => new
{
LastName = c.LastName,
Orders = o
}
);
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 3ms):
[
Hide/Show]
Last name: Gottshall
– Order number: Order 1
– Order number: Order 2
Last name: Valdes
Last name: Gauwain
Last name: Deane
– Order number: Order 3
– Order number: Order 4
Last name: Zeeman
– Order number: Order 5
Top
EditListing 4-18 : One-many join using sub-query syntax.
This sample demonstrates a one-many join using the sub-query syntax.
public void Listing_4_18_One_to_Many_SubQuerySyntax()
{
// Scenario: You have a customer, and need the orders
// for that customer
var customers = Customer.SampleData();
var orders = Order.SampleData();
var q2 = from c in customers
select new
{
LastName = c.LastName,
Orders = from o in orders
where o.CustomerID == c.CustomerID
select o
};
foreach (var customer in q2)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 1ms):
[
Hide/Show]
Last name: Gottshall
– Order number: Order 1
– Order number: Order 2
Last name: Valdes
Last name: Gauwain
Last name: Deane
– Order number: Order 3
– Order number: Order 4
Last name: Zeeman
– Order number: Order 5
Top
EditListing 4-19 : One-many join using ToLookup operator syntax.
This sample demonstrates a one-many join using the ToLookup operator syntax.
public void Listing_4_19_One_to_Many_ToLookupSyntax()
{
// Scenario: You have a customer, and need the orders
// for that customer
var customers = Customer.SampleData();
var orders = Order.SampleData();
// build a lookup list for the inner sequence
var orders_lookup = orders.ToLookup(o => o.CustomerID);
var q3 = from c in customers
select new
{
LastName = c.LastName,
Orders = orders_lookup[c.CustomerID]
};
foreach (var customer in q3)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
Console output (Execution time: 18ms):
[
Hide/Show]
Last name: Gottshall
– Order number: Order 1
– Order number: Order 2
Last name: Valdes
Last name: Gauwain
Last name: Deane
– Order number: Order 3
– Order number: Order 4
Last name: Zeeman
– Order number: Order 5
Top
EditListing 4-17,18,19 : One-Many joins two collections.
This sample demonstrates the different ways to achieve one-many joins between two collections and compares their performance.
public void Listing_4_One_to_Many_Performance()
{
// comment out one of the two following lines for test
//var loopOuter = 19; // 100 outer records
//var loopOuter = 9; // 50 records
var loopOuter = 0; // 5 outer records
var customers = Customer.SampleData();
for (int i = 0; i < loopOuter; i++)
customers = customers.Union(Customer.SampleData()).ToList();
var orders = Order.SampleData();
// You have a customer, and need the orders for that customer
// GroupJoin or "join into" syntax
var q1 = from c in customers
//where c.CustomerID == "DEA1"
join o in orders on c.CustomerID equals o.CustomerID
into cust_orders
select new
{
LastName = c.LastName,
Orders = cust_orders
};
var q1a = customers
//.Where(c => c.CustomerID == "DEA1")
.GroupJoin(
orders,
c => c.CustomerID,
o => o.CustomerID,
(c, o) => new {
LastName = c.LastName,
Orders = o }
);
// inner join sample, exclude customers with no orders
// q. why does this take 14 seconds????
var q1b = from c in customers
//where c.CustomerID == "DEA1"
join o in orders on c.CustomerID equals o.CustomerID
into cust_orders
where cust_orders.Any()
select new
{
LastName = c.LastName,
Orders = cust_orders
};
// subquery syntax
var q2 = from c in customers
//where c.CustomerID == "DEA1"
select new
{
LastName = c.LastName,
Orders = from o in orders
where o.CustomerID == c.CustomerID
select o
};
// ToLookup syntax
var orders_lookup = orders.ToLookup(o => o.CustomerID);
var q3 = from c in customers
//where c.CustomerID == "DEA1"
select new
{
LastName = c.LastName,
Orders = orders_lookup[c.CustomerID]
};
var q1p = from c in customers
//where c.CustomerID == "DEA1"
join o in orders.AsParallel() on c.CustomerID equals o.CustomerID
into cust_orders
select new
{
LastName = c.LastName,
Orders = cust_orders
};
Console.WriteLine("q1 = {0}ms, q2 = {1}ms, q3 = {2}ms, q1p = {3}ms",
MeasureTime(delegate { q1.ToList(); }, 1000000),
MeasureTime(delegate { q2.ToList(); }, 1000000),
MeasureTime(delegate { q3.ToList(); }, 1000000),
MeasureTime(delegate { q1p.ToList(); }, 1000000)
);
Console.WriteLine(Environment.NewLine + "Join syntax:");
foreach (var customer in q1)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
Console.WriteLine(Environment.NewLine + "Subquery syntax:");
foreach (var customer in q2)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
Console.WriteLine(Environment.NewLine + "ToLookup syntax:");
foreach (var customer in q3)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
Console.WriteLine(Environment.NewLine + "Parallel syntax:");
foreach (var customer in q1p)
{
Console.WriteLine("Last name: {0}", customer.LastName);
foreach (var order in customer.Orders)
Console.WriteLine(" – Order number: {0}", order.OrderNumber);
}
}
public class Customer
{
public string CustomerID { get; set; }
public string LastName { get; set; }
public static List<Customer> SampleData()
{
return new List<Customer> {
new Customer { CustomerID = "GOT1", LastName = "Gottshall"},
new Customer { CustomerID = "VAL1", LastName = "Valdes"},
new Customer { CustomerID = "GAU1", LastName = "Gauwain"},
new Customer { CustomerID = "DEA1", LastName = "Deane"},
new Customer { CustomerID = "ZEE1", LastName = "Zeeman"}
};
}
}
public class Order
{
public string CustomerID { get; set; }
public string OrderNumber { get; set; }
public static List<Order> SampleData()
{
return new List<Order> {
new Order { CustomerID = "GOT1", OrderNumber = "Order 1"},
new Order { CustomerID = "GOT1", OrderNumber = "Order 2"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 3"},
new Order { CustomerID = "DEA1", OrderNumber = "Order 4"},
new Order { CustomerID = "ZEE1", OrderNumber = "Order 5"}
};
}
}
Console output (Execution time: 7984ms):
[
Hide/Show]
Top