The Language Integrated Query

Introduction to Querying

When using a list of values or a collection of records, a query is a list created or selected from another existing list. This is usually the basis for a computer database. In fact, whole computer languages were developped on that theory. To make it possible to create a query based on any type of list, Microsoft created the Language Integrated Query, also named LINQ.

LINQ is a data manipulated language (DML) used to create a list or sub-list derived from an existing list or a collection of records. The LINQ is part of the .NET Framework. It is used along with normal C# code, but many other languages support their own syntaxes of LINQ.

Practical LearningPractical Learning: Introducing LINQ Applications

  1. Start Microsoft Visual Studio 2022

    Create New Project

  2. In the Visual Studio 2022 dialog box, click Create a New Project
  3. In the Create a New Project wizard page, in the languages combo box, select C#

    Create New Project

  4. In the list of the projects templates, click Windows Forms App
  5. Click Next
  6. In the Configure Your New Project dialog box, change the project Name to Exercise1
    Accept or change the project Location
  7. Click Next
  8. In the Framework combo box, select the highest version: .NET 8.0 (Long-Term Support)
  9. Click Create
  10. Double-click an unoccupied area of the form to generate its Load event
  11. To execute, on the main menu, click Debug -> Start Without Debugging
  12. Close the form and return to your programming environment
Author Note

Author Note

If you want, using the form of the application you created, you can apply the descriptions in the following sections to experiment with, and get, the same results.

Starting to LINQ

To support the ability to query a list, the .NET Framework provides the Language Integrated Query or LINQ. But LINQ is not a library; it is a part of a language. It allows you to create data-related lists from an existing list. This means that, unlike SQL that supports its own ability to perform all CRUD (Create, Read, Update, and Delete) operations related to a database, before using the LINQ, you must have a list already, which is really easy to create, as we will see.

To use the LINQ in your application, you must include the System.Core.dll assembly in your program. If you create a C# application in Microsoft Visual Studio, that assembly and everything necessary should be automatically included so that you don't have to formally include any separate library. For example, if you create a Console App or a Windows Forms Application in Microsoft Visual Studio, the studio would automatically add the necessary assemblies to your project and the necessary namespaces to your project.

Creating a Query

To query a list, you write a statement using words and operators of the LINQ. The most fundamental operation you can perform on LINQ consists of creating, also referred to as selecting, or querying, a list of values or records, from an existing list. The basic formula to use is:

var sub-list-name = from value-holder in list select value-holder;

The var keyword, the assignment operator "=", the from keyword, the in keyword, the select keyword, and the semicolon are required.

The sub-list-name is a name of a new variable that will hold the list of values produced by this operation.

The value-holder is the name of a variable that will be used to identify each resulting member of this operation. This variable will be equivalent to getting each member of the list.

The list factor represents the name of the variable that you would have created already. The list can be an array. When the statement ends, the sub-list-name is the list that is produced. That's the list you will used outside the statement.

Querying an Array

As you may be aware already, the array is the most fundamental type of list in C#, and you should know already how to create an array of values. Here is an example of an array of integers:

var numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 };

The array is also the most fundamental list you can query. From our formula, the simplest query you can perform on an array consists of getting its values and storing them in a query variable. To do this, from our formula, replace sub-list-name with a variable name of your choice. Replace value-holder with the name that will be selec-ted at the end. Replace list with the name of your array. Here is an example of simply querying an array:

namespace Numbers
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 };

            var number = from n in numbers select n;

            foreach (var member in number)
                lbxNumbers.Items.Add(member.ToString());
        }
    }
}

This would produce:

Numbers

To make the code easier to read, you can spread the statement to various lines. Here is an example:

var number = from n
	     in numbers
	     select n;

When a Variable is not Necessary

If you plan to use the result of a query many times, you can declare a variable and store the query in it as we have done so far. Here is an example:

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            float[] timesWorked = new float[] { 8.50f, 7f, 6.50f, 8.0f, 9.00f };

            var values = from number in timesWorked select number;

            foreach (var member in values)
                lbxNumbers.Items.Add(member.ToString("N"));
        }
    }
}

This would produce:

Numbers

If you are planning to use the result of a query only once, you don't have to declare a variable for it. You can create the query directly where it is needed. Here is an example:

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            
            var values = from number
			 in new float[] { 8.50f, 7f, 6.50f, 8.0f, 9.00f }
			 select number;

            foreach (var member in values)
                lbxNumbers.Items.Add(member.ToString("N"));
        }
    }
}

If you are using the result of a query only in a conditional statement, you can write the query statement directly in the conditional statement where it is needed. Here is an example:

namespace Exercises
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            foreach (var member in from number
				   in new float[] { 8.50f, 7f, 6.50f, 8.0f, 9.00f }
				   select number)
                lbxNumbers.Items.Add(member.ToString("N"));
        }
    }
}

Nesting a Query

Consider a simple query the types we have learned so far:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var numbers = new double[] { 12, 447, 1285, 250, 15750, 388, 646, 2500, 6320 };

            var number = from nbr
                         in numbers
                         select nbr;

            foreach (var member in number)
                lbxNumbers.Items.Add(member.ToString());
        }
    }
}

This would produce:

Numbers

In the same way, you can have different queries in your application. Here are examples:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            int[] numbers = new[] { 12, 447, 1285, 250, 15750, 388, 646, 2500, 6320 };
            double[] values = new[] { 513.28d, 50.5d, 6.83d, 450.61d };

            var number = from nbr
                         in numbers
                         select nbr;

            var things = from val
                         in values
                         select val;

            foreach (var n in number)
                lbxNumbers.Items.Add(n.ToString());

            foreach (var v in things)
                lbxSelections.Items.Add(v.ToString());
        }
    }
}

This would produce:

Numbers

Remember that, when you are creating a query, you start with a formula as follows:

var sub-list-name = from value-holder
    in list
    select value-holder;

In this formula, you use a list that you can get from a variable. In some cases, you may want to use that itself emanates from a query. In that case, you can replace the list with a query. The formula to follow becomes:

var sub-list-name = from value-holder
    		    in from value-holder
			    in list
    			    select value-holder
    	 	    select value-holder;

This is referred to as nesting a query. This means that, where you would have written the name of a (variable that holds a) list, you can create a query. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            int[] numbers = new[] { 12, 447, 1285, 250, 15750, 388, 646, 2500, 6320 };
            double[] values = new[] { 513.28d, 50.5d, 6.83d, 450.61d };

            var number = from nbr
                         in numbers
                         select nbr;

            var things = from val
                         in from nbr
                            in numbers
                            select nbr
                         select val;

            foreach (var n in number)
                lbxNumbers.Items.Add(n.ToString());

            foreach (var v in things)
                lbxSelections.Items.Add(v.ToString());
        }
    }
}

This would produce:

Numbers

To make your code easy to read, you should put the nested query in parentheses. This can be done as follows:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            int[] numbers = new[] { 12, 447, 1285, 250, 15750, 388, 646, 2500, 6320 };
            double[] values = new[] { 513.28d, 50.5d, 6.83d, 450.61d };

            var number = from nbr
                         in numbers
                         select nbr;

            var things = from val
                         in (from nbr
                            in numbers
                            select nbr)
                         select val;

            foreach (var n in number)
                lbxNumbers.Items.Add(n.ToString());

            foreach (var v in things)
                lbxSelections.Items.Add(v.ToString());
        }
    }
}

Sorting the Results of a Query

Introduction

Sorting a list consists of re-arranging its members in a certain order. The arrangement depends on the type of values. That is, the list can be arranged in alphabetical order, in ascending order, in chronological order, in incremental order, or in logical order.

Sorting in Ascending Order

When you create a list, you add the items in any order of your choice. When you create a select statement, the items are added to its list in the order they appear in the original list. When treating the new list or when presenting it to the user, you may want to arrange it in alphabetical, numerical, or chronological order. To support this operation, the LINQ provides an operator named orderdy. To apply it, write the operator before the select operation followed by the from list. Here is an example:

namespace Numerotation
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            var numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 };

            var regularOrder = from n
                               in numbers
                               select n;

            foreach (var member in regularOrder)
                lbxRegularOrder.Items.Add(member.ToString());

            var sortedOrder = from n
                              in numbers
                              orderby n
                              select n;

            foreach (var member in sortedOrder)
                lbxSortedOrder.Items.Add(member.ToString());
        }
    }
}

This would produce:

Numbers

If you apply the orderby operator simply followed by a variable, the list is ordered alphabetically or numerically depending on the types of values in the list. This is referred to as ascending. To re-enforce this, you can follow the variable with the ascending keyword. Here is an example:

var sortedOrder = from n
                  in numbers
                  orderby n ascending
                  select n;

Sorting in Descending Order

You can arrange a list in reverse ascending order, in decremental order, or in reverse chronological order. To support this, the LINQ uses a keyword named descending. It is used in combination with the orderby keyword. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    var numbers = new double[] { 12.44, 525.38, 6.28, 2448.32, 632.04 };

    var regularOrder = from n
                       in numbers
                       select n;

    foreach (var member in regularOrder)
        lbxRegularOrder.Items.Add(member.ToString());

    var sortedOrder = from n
                      in numbers
                      orderby n descending
                      select n;

    foreach (var member in sortedOrder)
        lbxSortedOrder.Items.Add(member.ToString());
}

This would produce:

Numbers

Practical LearningPractical Learning: Ending the Lesson


Home Copyright © 2014-2024, FunctionX Friday 04 November 2022 Next