from Clause

The from clause defines information|the info|the information} supply that you’ll get data from. The from clause is answerable for iterating every knowledge from the info supply. The from clause starts question|a question |a question} expression so the remainder of the query expression can understand what quite knowledge it’s operating with. thanks to it, Visual Studio will use the Intellisense when the from clause as a result of it currently is aware of the kind of each item from the info supply. the subsequent shows the essential structure of a from clause.

from dataType rangeVar in dataSource

It starts with the from keyword which is a contextual keyword in C#. We then need to declare a range variable which is an iterator variable that will hold every value from the data source. You can specify the data type of the range variable which has a more specific use as we will see later. The in keyword is next followed by the actual data source that implements the IEnumerable or IEnumerable<T>interfaces.

What happens in a typical query is it iterates each value from the data source and places each value from the range variable. You can then do more kinds of operation to these variable such as testing if it meets a certain condition. Again, remember deferred execution which means that LINQ will not execute until you request a data from the result of the query using a foreach loop or retrieving a single item.

Here’s an example of a from clause:

from int number in numbers

The from clause above instructs the computer to retrieve every number in the numbers collection (assuming that the numbers collection is an array or an IEnumerable object). Note the indication of the data type after the from keyword. Most of the time, it is totally fine to just omit this if you are sure of the type of every data from the data source.

from number in numbers

The compiler can just infer the type of the range variable based on the type of the collection. For example, if the collection is an IEnumerable<Person>, then the range variable will be of type Person.

But if you are querying a collection of objects such as an ArrayList, it would be better to explicitly indicate the type of every item from the data source. Consider the following example:

ArrayList persons = new ArrayList();
persons.Add(new Person("John", "Smith"));
persons.Add(new Person("Mark", "Chandler"));
persons.Add(new Person("Eric", "Watts"));

var query = from p in persons
            select p;

You will receive the following error at compile time:

Could not find an implementation of the query pattern for source type 
'System.Collections.ArrayList'. 'Select' not found. Consider explicitly specifying the 
type of the range variable 'p'.

The compiler demands you to explicitly indicate the type of each item from the data source since ArrayList can contain objects of different types. To fix this, simply indicate the type that you are expecting for every item in the collection:

from Person p in persons

The query then does casting on every item to convert every object from the ArrayList into a Person object. If an item from the ArrayList cannot be cast to the type indicated in the query, then an exception will be thrown.

The from clause was strategically placed at the beginning of a query expression so that Visual Studio will immediately know the type of data you are working with. As seen below, right after the from clause, you can already enjoy the benefits of the IntelliSense feature of Visual Studio.

The from clause 01

Figure 1

Joining Multiple Tables Using Multiple from Clauses


If you have two data sources, you can actually join them by using multiple from clauses. Consider this simple code that joins two sets of numbers.

int[] numberSet1 = { 1, 2, 3, 4, 5 };
int[] numberSet2 = { 6, 7, 8, 9, 10 };

var query = from n1 in numberSet1 
            from n2 in numberSet2 
            select String.Format("{0},{1}", n1, n2); 

foreach (var n in query)
{
    Console.WriteLine(n.ToString());
}

Example 1

(1,6)
(1,7)
(1,8)
(1,9)
(1,10)
(2,6)
(2,7)
(2,8)
(2,9)
(2,10)
(3,6)
(3,7)
(3,8)
(3,9)
(3,10)
(4,6)
(4,7)
(4,8)
(4,9)
(4,10)
(5,6)
(5,7)
(5,8)
(5,9)
(5,10)

We used two from clauses which retrieves data from two separate data sources. Within format the result in the select clause. As you can see in the output, every possible combination was added to the query result. This type of combination is called an inner join. You can also use the join clause which will be tackled in a separate lesson.

Note that a second or third from clause does not necessarily need to immediately follow the first from clause. You can create a query like this:

from n1 in numberSet1
where n1 > 2
from n2 in numberSet2
select String.Format("({0},{1})", n1, n2);

A single from clause does not have an equivalent query method in the System.Linq. You can simply use the Select() and other methods. Be that as it may, for various from conditions, you can utilize the SelectMany() method which will have its own particular devoted exercise.

Creating Relationships on Classes


Multiple from clauses may also effectively be used for connected categories. however such categories should be properly structured 1st. to Illustrate, a Customer can have multiple orders which might be thought-about as one-to-many relationship (one client to several orders). Let’s take a glance at however we are able to properly outline our Customer and Order classes.

class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<Order> Orders { get; set; }
}

Example 2

The Customer class has solely 3 properties to form things straightforward. The third property defines its relationship with the Order class. it’s a List of Order objects that represents the orders created by the client. The Order class is shown in Example three.

class Order
{
    public string (variable name) { get; set; }
    public int (variable quantity) { get; set; }
}

Example 3

Presently how about we make some Customer objects and relegate a few requests to their Orders property.

class Program
{
    static void Main(string[] args)
    {
        List<Customer> customers = new List<Customer>();
 
        Customer customer1 = new Customer()
        {
            First = "John",
            Last = "Smith",
            Orders = new List<Order>()                          
            {                                                     
                new Order() { Name = "Pizza", Quantity = 5 },      
                new Order() { Name = "Chicken", Quantity = 3 }, 
                new Order() { Name = "Salad", Quantity = 7 }    
            }                                                   
        };
 

        Customer customer2 = new Customer()
        {
            First = "Allan",
            Last = "York",
            Orders = new List<Order>()                                       
            {                                                                      
                new Order() { Name = "Orange Juice", Quantity = 2 },               
                new Order() { Name = "Soda", Quantity = 4 }                        
            }                                                       
        };
 
        Customer customer3 = new Customer()
        {
            First = "Henry",
            Last = "Helms",
            Orders = new List<Order>()                                       
            {                                                                      
                new Order() { Name = "Speghetti", Quantity = 7 },                  
                new Order() { Name = "Nachos", Quantity = 13 }                     
            }                                                     
        };
 
        customers.Add(customer1);
        customers.Add(customer2);
        customers.Add(customer3);
 
        var results = from c in customers                                        
                      from o in c.Orders 
select new { c.First, c.Last, o.Name, o.Quantity };
 
        foreach (var result in results)
        {
            Console.WriteLine("Name: {0} {1}, Order: {2}, Quantity: {3}",
                result.First, result.Last, result.Name, result.Quantity);
        }
    }
}

Example 4

Name: John Smith, Order: Pizza, Quantity: 5
Name: John Smith, Order: Chicken, Quantity: 3
Name: John Smith, Order: Salad, Quantity: 7
Name: Allan York, Order: Orange Juice, Quantity: 2
Name: Allan York, Order: Soda, Quantity: 4
Name: Henry Helms, Order: Speghetti, Quantity: 7
Name: Henry Helms, Order: Nachos, Quantity: 13

As you can see in the output, each customer’s order is shown. We can properly  organize the output by using the group-by clause  which will be discussed later. In lines 7-40 of Figure 3, we created three Customer objects, each having their Orders property initialize with some Order objects. We added the three created Customers in the customers  list.

Lines 46-48 shows a query expression with two from clauses. The first from clause retrieves a Customer object from the customers list. The  second from clause retrieves an Order from the Orders  property of the retrieved Customer. The select clause uses projection to include the FirstName and LastName  properties of the customer, and the Name and Quantity properties of the order. Lines 50-54  prints the results.

Designing your classes like these is great because it is very simple to  determine the relationship of objects and the needed data. Database tables often have these kinds of relationships. Visual Studio has tools that can  automatically generate classes that map to these tables together with their  relationship to other tables exposed as properties. You will more about this  when we reach LINQ to SQL.