News


Cross join consists to perform a Cartesian product of two sets or sequences. The following example shows a simple Cartesian product of the sets A and B:

A (a1, a2)

B (b1, b2)

=> C (a1 b1,

           a1 b2,

           a2 b1,

           a2, b2 ) is the Cartesian product's result.

Linq to Sql allows using Cross join operations. Cross join is not equijoin, means that no predicate expression of equality in the Join clause of the query.

To define a cross join query, you can use multiple from clauses. Note that there's no explicit operator for the cross join.

In the following example, the query must join a sequence of Product with a sequence of Pricing Rules:

   1: //Fill the data source
   2: var products = new List<Product>
   3: {
   4:       new Product{ProductID="P01",ProductName="Amaryl"},
   5:       new Product {ProductID="P02", ProductName="acetaminophen"}                
   6: };
   7:  
   8: var pricingRules = new List<PricingRule>
   9: {
  10:       new PricingRule {RuleID="R_1", RuleType="Free goods"},
  11:       new PricingRule {RuleID="R_2", RuleType="Discount"},
  12:       new PricingRule {RuleID="R_3", RuleType="Discount"}
  13: };
  14:   
  15: //cross join query
  16: var crossJoin = from p in products
  17:                 from r in pricingRules
  18:                 select new { ProductID = p.ProductID, RuleID = r.RuleID };

 

Below the definition of the two entities using in the above example.

 

   1: public class Product
   2: {
   3:     public string ProductID { get; set; }
   4:     public string ProductName { get; set; }
   5: }
   1: public class PricingRule
   2: {
   3:     public string RuleID { get; set; }
   4:     public string RuleType { get; set; }
   5: }

 

Doing this:

   1: foreach (var result in crossJoin)
   2: {
   3:     Console.WriteLine("({0} , {1})", result.ProductID, result.RuleID);
   4: }

 

The output should be similar on this:

  ( P01   -    R_1 )

  ( P01   -    R_2 )

  ( P01   -    R_3 )

  ( P02   -    R_1 )

  ( P02   -    R_2 )

  ( P02   -    R_3)

Conclusion

Cross join operation is useful when performing a Cartesian product of two sequences object.

However, it can produce very large result sets that may caused a problem of performance. So use with precautions :)



First() and FirstOrDefault() are two extension methods of the Enumerable class. Extension method is a static method that we can call from an instance object which implement IEnumerable interface. Lets make an analysis of the following simple example.

 1:int[] number = { 1, 5, 6, 8, 20, 15, 34, 67, 98, 12, 23 };
 2:var num = number.Where(n => n > 100).First(); 
 3:Console.WriteLine("First Number greater than 100: {0}", num); 

By definition, First() method return the first element of a sequence. So if we run this code, it throws an error:

InvalidOperationException was unhandled

The error occurs because the sequence returned by the Where method contains no element.The First() method should be used when sequence contains at least one element, otherwise it throws an exception.

How to prevent this exception to happen:

We have two choices:

  • instead of "First()", use "FirstOrDefault()" that return default value whether sequence has no elements.
  •  1:var num = number.Where(n => n > 100).FirstOrDefault();

    The default value depend type of the element in sequence. Here the type is int so the default element is 0 (zero).

    As output, we have something like: First Number greater than 100 : 0

    What's happened if the type is an instance object? In this case, the defaut value is null.

  • or, setting the default value by using "DefaultIfEmpty()" method extension before call "First()" method.
  •  1:var num = number.Where(n => n > 100).DefaultIfEmpty(100).First(); 

    As output, we have something like: First Number greater than 100 : 100

Conclusion

The “First()” extension method should be used with precaution. Keep in mind that if the sequence might be empty, the best alternative is to use one of the two choice above.