Visual C

C# LANGUAGE FUNDAMENTALS Welcome to Visual C# Express 2010 It is essential to know the different parts of the Visual C#

Views 90 Downloads 1 File size 12MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

C# LANGUAGE FUNDAMENTALS Welcome to Visual C# Express 2010 It is essential to know the different parts of the Visual C# Express environment. You also need to know the different tools and features that this IDE can offer to you. Open Visual C# Express 2010, if this is your first time running the IDE, you need to wait for it to configure the initial settings for the user.

After the initial configuration, the Start Page of Visual C# Express 2010 will show up.

The numbered labels will be used to identify the different parts of the IDE.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Menu Bar The Menu Bar(1) is where the different menus for creating, developing, maintaining, debugging, and executing programs can be found. Clicking a menu will reveal another set of related menus. Note that the menu bar still has hidden menu items which will only show on certain conditions. For example, the Project menu item will show if a project is currently active. Here are some of the description of each menu item. The following are some of the menus and their description. Menu Item

Description

Contains commands to create new projects or files, open or save projects, exit or close projects, printing, and many file or project related tasks. Contains commands which are related to editing such as selecting, copying, pasting, Edit finding, and replacing. Allows you to open more windows that are initially hidden or add more toolbars items View to the toolbar. Project Contains commands related to the projects you are working on. Debug Allows you to compile, debug(testing), and run the project. Contains command for connecting or creating different datasources for use in your Data application. Contains commands for arranging the layout of GUI components while in the Design Format View. Tools Contains the different tools, settings, and options for VS/VCE. Window Allows you to adjust the view or layout of the windows inside VS/VCE. Allows you to view the documentation and help topics, product registration details, Help and product version details. File

The Toolbars The Toolbars(2) contain commonly used commands which are also found in the menu bar. The toolbars serve as a shortcut to commands located in the menu bar. Each buttons has an icon that represents their functionality. You can hover each button to show a tool tip that describes their functionality. Some commands are initially hidden and will only show up on appropriate situations. You can also right click to any blank area of the toolbar to add more commands. Alternatively, you can go to View > Toolbars and check items to show up more toolbars. Some buttons have arrows beside them that when clicked, shows more related commands. You can also click the arrows beside each toolbar that will allow you to add or remove more buttons to tool bar. The left side of each toolbar allows you to move or change the arrangement of toolbars.

The Start Page

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will see some tips, tutorials and news in the Start Page(3) section of the IDE. You can also create or open projects from here. If you have created some projects, then they will show up here in the Recent Projects section so you won't have a hard time finding each project. You can access the latest news related to .NET and Visual Studio by going to the Latest News tab. You can open VS/VCE's internal browser by going to View > Other Windows > Web Browser. There is more to explore in Visual C# Express and more parts of the program and features will be explained in the following lessons.

Registering Visual C# Express 2010 Visual C# Express is free, but you need to register the product to be able to use it permanently. You need to obtain a key from Microsoft to activate your copy of Visual C# Express. Note that this key will be given to you for free after following the steps in this lesson. Open Visual C# Express and on the Menu Bar, go to Help > Register Product.

You will be presented with a window asking for a Registration Key. Click "Obtain a registration key online" to begin the process of obtaining the key. An internet connection is required for the following process.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will be taken to a page where you will be asked to log in your Windows Live ID. If you already have a Windows Live ID account, then you can sign in. If you currently don't have an account, you need to sign up for a new one by clicking the "Sign up now" button.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Copy the registration key and go back to Visual C# Express. Paste the key to the text box in the Registration Window and then click "Register Now". That's it, you can now use Visual C# Express permanently.

Exploring Visual C# Express 2010 Visual C# Express has lots of windows and components that provides functionality or displays certain informations. Let's further explore the different parts of Visual C# Express by going deeper into the IDE. Create a new Windows Forms Application by going to File > New Project or using the shortcut Ctrl+Shift+N.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will be presented with the New Project Window.

To the left is a list of categories of installed templates. Since you are using Visual C# Express, only C# is available. The center of the window shows the installed template for the specified category. Templates are precreated project files which are provided to you so you will not create them from scratch. All you have to do is create a project from a template and start programming. The number of templates listed varies depending on the templates installed in your computer. You can sort the name of the templates by ascending or descending order by using the combo COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

box(drop down box) found at the top center. You can change the view of the templates by clicking the buttons next to that combo box. The right side shows a search box for searching installed templates and the description of the selected template. Choose Windows Forms Application from the list of templates. You can name your project using the text box found at the bottom. For now, leave it as it is. Click OK to generate a project from the selected template.

Figure 1 - Newly created Windows Forms Application Project

The Designer The Designer(1) is like your canvas or drawing area for designing windows forms. Windows forms are graphical user interfaces and you see them everywhere when you use computers. You add controls to the form such as buttons, text boxes, labels, and many more. A more detailed look at windows forms, controls, and visual programming is located at the Windows Forms Section of this site. But it is recommended to finish the basic and fundamental lessons first before creating windows forms application.

The Solution Explorer. The Solutions Explorer(2) shows the different projects and the files associated with the solution. A solution represents the application you are creating. It may compose of a single

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

project, or multiple projects, and each project is composed of files such as source code files and images. When you create a project, a solution is automatically created containing the project you have chosen. If the Solution Explorer is not visible, go to View > Other Windows > Solution Explorer or you can use the shortcut Ctrl+Alt+L. If multiple projects are present, the project in bold text is considered the Startup Project which is considered as the default project and the one that will run when you start debugging (more on this later). If the project you want to execute is not the startup project, right click the project in the Solution Explorer and then choose "Set as StartUp Project". Below is the Solution Explorer showing a Solution with 2 Projects. Each project contains files and folders associated to them.

The first button in its top bar allows you to edit the properties of the project. Some files located in the project directory are hidden in the Solution Explorer. You can click the second button to show all the hidden files.The third button refreshes the Solution Explorer in case files are added, deleted or modified. More buttons will show up depending on the current project or view you are working on. You can double click the files in the solution explorer to open them up or check their contents. You can also click the arrows to the left of each node to reveal child nodes they contain.

The Properties Window

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Properties Window(3) shows the different properties or events of any selected item such as files, projects, the form, or controls. If it is not visible to you, go to View > Other Windows > Properties Window or use the shortcut F4. We will have an in-depth discussion of properties and events in upcomming lessons. Properties can be considered as characteristics or attributes of objects. For example, a car has properties color, speed, size, and brand. If you are selecting a form or control in the Design View, or projects or files in the Solution Explorer, the Properties Window will show the properties available for them.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Properties Window also allows you to view the events of a selected control or form. An event is something that happens when certain conditions occur such as when a button is clicked or when the text inside the text box is modified. The top combo box(A) allows you to choose the object whose properties will be shown in the Properties Window. This is useful when you can't select certain controls(probably because of their small size) in the Designer. Below the combo box shows some helpful buttons(B). Some buttons only appear on certain instances. The first button will arrange the properties in different categories. The second button will arrange the properties in alphabetical order. I recomend pressing this button as I found it easier to find the properties you want when it is alphabetized. The third and fourth buttons only appear when you are selecting a control or a form in the designer view. The third button allows you to view the available properties of the current selected control or form. The fourth button (indicated by the thunder bolt icon) shows the available events for the selected control or form. The bottom box shows the description of the selected property or event. The main part of the properties window(C) contains the properties or the events. The left column specifies names of the properties or event. The right column shows the values of the properties and events. There are simple properties that require a single value, but there are also complex properties that consist of more properties. These can be identified with an arrow on the left of those properties. If you click that arrow, subproperties of the property are shown. Some properties opens up special tools or windows when normal text input cannot be accepted. The bottom part of the Properties Window is the Description Box(D) which shows the description of functionality of the selected property or event.

Changing the Layout of Visual C# Express If you don't like the position of the windows, or the layout of the IDE, you have the ability to arrange them. By clicking and dragging the title bar of each window, you can make them float as shown below.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 1 - Guides are shown to aid in docking the windows While still draging the window, a guide used for docking will show up. This allows you to dock the window on certain locations of the IDE. For example, you can drag the window to the topmost box to dock it to the top. The area where the item being dragged will be docked will turn blue.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 2 - The area where the window will be docked is colored with blue

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 3 - Window is docked at the top portion of the IDE The central cross guide containing different boxes allows you to dock the window to certain parts of another window. For example, dragging the window to the left-most part of the cross while in the design view will dock the control to the left side of the Design View.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Dragging the window to the center of the cross will combine the window being dragged to the destination Window, in the case above, the Design Window and you can access the Properties Window via a tab.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

If you drag the Properties Window over the Solution Explorer for instance, another cross guide will show up. Draging the the window to the bottom of the guide will dock the Properties Window below the Solution Explorer.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The destination where your window will be docked will be partially filled with a blue color to notify you how it will be docked. Visual C# Express also offers a space saving feature called autohide which automatically hides the window. Each window has a pin icon next to the close button.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Clicking this icon will "unpin" the window and activate the auto-hide feature. You can now access the windows by hovering your mouse or clicking the tabs at the side of the IDE. Notice the large space saved by using the autohide feature.

To "pin" or disable the autohide feature of a window, simply access the window and clicked the pin icon again.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Notice that the pin is now horizontal. A vertical pin indicates that the window is pinned while a horizontal pin indicates that the window is unpinned and will auto-hide.

Creating a Simple Program Let's create our very first program using the C# programming language. The program will print a line of message in the console window. Note that we will be using Console Application as the project type for the following tutorials. This is just an overview of what you will learn in the following lessons. I will explain here the structure and syntax of a simple C# program. Open up Visual C# Express. Go to File > New Project to open the New Project Window. You will be presented with a window asking you of the type and name of project you want to create.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 1 - New Project Window Choose Console Application as the project type and name it MyFirstProgram. A Console Application is a program that runs in command prompt(console) and has no visual or graphical interface. You will deal with this type of project because it will be easier to demonstrate the language concepts compared to using windows forms. We will begin with visual programming once we are finished with the fundamentals of this language. After pressing OK, Visual C# Express will create a solution file in a temporary directory. A solution is a collection of projects but for most of the tutorials, solutions only contain 1 project. The solution file with file extension .sln contains details about the projects and files associated with it and many more. Creating a new project also creates a .csproj file which contains details about the project and its associated files. Since we choosed Console Application as the project type, there will be no Designer. Instead, we are presented with the Code Editor.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 2 - Code Editor The Code Editor is where you type your codes. Codes typed in the editor are color coded so it will be easier for you to recognize certain parts or components of your code. Color Coding is another great feature of the Visual Studio family. The combo box to the top left(1) will list all the classes, structures, enumerations, and delegates in the code and the combo box to the top right(2) will list all the members of the class, structure, or enumeration where the cursor is positioned inside. Don't worry about the terms I used, they will be discussed in later lessons. A .cs file named Program.cs is created and is contained by the project. It will contain the codes for your program. All C# code files has .cs file extensions. You will be presented with a prewritten code to get you started, but for now, delete everything and replace it with the following code: 1 namespace MyFirstProgram 2 { 3 class Program 4 { 5 static void Main() 6 { 7 System.Console.WriteLine("Welcome to Visual C# Tutorials!"); 8 } 9 }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

10}

Example 1 - A Simple C# Program The numbers to the right are not part of the actual code. They are only there so it will be easier to reference which code is being discussed by simply telling their associated line number(s). In Visual C# Express, you can go to Tools > Options > Text Editor > C# and then check the Line Numbers check box to show line numbers in your Visual C# Express or Visual Studio code editor.

Structure of a C# Program The code in Example 1 is the simplest program you can make in C#. It's purpose is to display a message to the console screen. It has a nice structure which is easy on the eyes compared to other programming languages. Every language has its own basic syntax, which are rules to follow when writing your code. Let's try to explain what each line of code does. Line 1 is a namespace declaration, which declares a namespace used as containers for your codes and for avoiding name collisions. Namespaces will be covered in detail in another lesson. Right now, the namespace represents the name of your project. Line 2 is a { symbol which is called a curly brace. Curly braces defines a code block. C# is a block-structured langauge and each block can contain statements or more valid code blocks. Note that each opening curly brace ( { ) should have a matching closing brace ( } ) at the end. Everything inside the curly braces in Line 2 and 10 is the code block or body of the namespace. Line 3 declares a new class. Classes are a topic of object oriented programming and you will learn everything about it in later lessons. For now, the codes you write should be contained inside a class. You can see that it also has its own pair of curley braces (Line 4 and 9), and everything between them is the class' code block. Line 5 is called the Main method. A method encapsulates a code and then executes it when the method is called. Details in creating a method will be explained in a later lesson. The Main method is the starting point of the program. It means that it is the entry point of execution and everything inside the Main method are the first ones to execute after all the initializations have been completed. Picture the Main method as the front door of your house. You will learn more about the Main method in a later lesson. The Main method and other methods you will create also has a set of curly braces which defines its code block and inside it are the statements that will be executed when the method is called. Statements are another term for a line of code in C#. Each statements must end with a semicolon (;). Forgetting to add the semicolon will result in a syntax error. Statements are located inside code blocks. An example of a statement is the following code (Line 7): System.Console.WriteLine("Welcome to Visual C# Tutorials!");

This is the code that displays the message "Welcome to Visual C# Tutorials!". We need to use the WriteLine() method and pass the string message inside it. A string or string literal, is a group COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

of characters and they are enclosed in double quotes ("). A character is any letter, number, symbol, or punctuation. For now, the whole line simply means "Use the WriteLine method located in the Console class which is located in the System namespace". More of these will be explained in the upcoming lessons. C# ignores spaces and new lines. Therefore, you can write the same program in Example 1 in just one line. But that will make your code extremely hard to read and debug. Also keep in mind that statements don't necessarily need to be in one line. One common error in programming is adding semicolons at every end of a line even though multiple lines represent a single statement. Consider the following example. System.Console.WriteLine( "Welcome to Visual C# Tutorials!");

Since C# ignores white space, the above snippet is acceptable. But the following is not. System.Console.WriteLine( ; "Welcome to Visual C# Tutorials!");

Notice the semicolon at the end of first line. This will produce a systax error because the two lines of code are considered as one statement and you only add a semicolon at the end of a single statement. Some statements such as the if statement can have their own code blocks and you don't have to add semicolons at the end of each block. Always remember that C# is a case-sensitive language. That means you must also remember the proper casing of the codes you type in your program. Some exceptions are string literals and comments which you will learn later. The following lines will not execute becase of wrong casing. system.console.writeline("Welcome to Visual C# Tutorials!"); SYSTEM.CONSOLE.WRITELINE("Welcome to Visual C# Tutorials!"); sYsTem.cONsoLe.wRItelIne("Welcome to Visual C# Tutorials!");

Changing the casing of a string literal doesn't prevent the code from running. The following is totally okay and has no errors. System.Console.WriteLine("WELCOME TO VISUAL C# TUTORIALS!");

But what will be displayed is exectly what you have indicated in the string literal. Also notice the use of indention. Everytime you enter a new block, the codes inside it are indented by 1 level. { statement1; }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This makes your code more pleasing to the eyes because you can easily determine which code belongs to which block. Although it is optional, it is highly recommended to use this practice. One great feature of Visual C# Express and Visual Studio is its auto-indent feature so you don't have to worry about indention when entering new blocks.

Saving Your Project and Solution To save your project and solution, you can go to File > Save All or use the shortcut Ctrl+Shift+S. You can also access this command in the toolbar. It is represented by multiple diskettes.

You will then be prompted with Save Project Window.

The Name field will already be filled with the Name you provided when you created the project. The Location field specifies where you want to save the project. Click the Browse button to select a location in your disk. The Solution Name field specifies the name for the solution. Leave the checkbox checked so VCE will create a folder for your solution located on the specified path in the Location field. Click Save to finish saving. If you simply want to save a single file, go to File > Save (FileName) where FileName is the name of the file to be saved. You can use the shortcut Ctrl+S or click the single diskette icon in the toolbar beside the Save All icon. To open a project or solution file, go to File > Open, or find the folder icon in the toolbar right before the save icon. Browse for the project of solution file. A solution file has an extension name of .sln and a project file has an extension name of .csproj. When opening a solution file, all the linked project to that solution will be opened as well together with the files associated for each of the projects.

Compiling the Program We learned that our code needs to be compiled first to Microsoft Intermediate Language before we can run it. To compile our program, go to Debug > Build Solution or simply hit F6. This

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

will compile all the projects within the solution. To build a single project, go to the Solution Explorer and right click a project, then select Build.

Rebuild simply recompiles a solution or project. I will not require you to always build the project if you will simply run the program because executing the program (as described next) automatically compiles the project. You can now find the executable program of your project with .exe extension. To find this, go to the solution folder at the location you specified when you saved the solution/project. You will find here another folder for the project, and inside, find the folder named bin, then enter the Release folder. There you will finally find the executable file. (If you can't find it in the Release folder, try the Debug folder).

Executing the Program When we execute a program, Visual C# Express automatically compiles our code to Intermediate Language. There are modes of executing/running a program, the Debug Mode and the NonDebug Mode. The Non-Debug Mode runs or executes the program disabling the debugging features of the IDE. The program will be executed the same way it will be executed when it is run by the user who will use your program. By running the program in Non-Debug mode you will be prompted to enter any key to continue once the program reaches the end. By default, the command for running in Non-Debug Mode is hidden if you are using the Basic Settings. We need to switch to

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Expert Settings to expose more options in the menu. Go to Tools > Settings then check Expert Settings. Wait for the IDE to finish adjusting settings. You can now run in Non-Debug mode by going to Debug > Start Without Debugging in the menu bar. You can also use the shortcut Ctrl+F5. You will get the following output: Welcome to Visual C# Tutorials! Press any key to continue . . .

Note that the message "Press any key to continue..." is not part of the actual output. This will only show if you run your program in Non-Debug mode. It is only there to prompt you to press any key to exit or continue the program. The Debug Mode is easier to access and is the default for running programs in Visual C# Express. This mode is used for debugging(testing for errors) which will be discussed in a future lesson. You will be able to use break points and helper tools when exceptions are encountered when your program is running. Therefore, I recommend you to use this mode when you wan't to find errors in your program during runtime. To run using Debug Mode, you can go to Debug > Start Debugging or simply hit F5. Alternatively, you can click the green play button located at the toolbar.

Using Debug Mode, you program will show and immediately disappear. This is because during Debug Mode, once the program reaches the end of code, it will automatically exit. To prevent that from happening, you can use the System.Console.ReadKey() method as a workaround which stops the program and asks the user for an input. (Methods will be discussed in detail in a later lesson.) namespace MyFirstProgram { class Program { static void Main() { System.Console.WriteLine("Welcome to Visual C# Tutorials!"); System.Console.ReadKey(); } } }

Example 2 - Using the Console.ReadKey() Method Now run the program again in Debug Mode. The program will now pause to accept an input from you, simply hit Enter to continue or exit the program. I would recommend to use the NonDebug mode just so we don't need to add the additional Console.ReadKey() code at the end. From now on, whenever I say run the program, I will be assuming that you use the Non-Debug mode unless otherwise noted. We will use Debug mode when we reach the topic of Exception Handling.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Importing Namespaces Namespaces in a nutshell are container of codes that you can use in a program. We defined our own namespace named MyFirstProgram but there are thousands of namespaces inside the .NET Framework Class Library. An example is the System namespace which contains codes that are essential for a basic C# application. The Console class we are using to print lines is actually inside the System namespace. We are using the fully qualified name of the Console class which includes the namespace System throughout this lesson. System.Console.WriteLine("Welcome to Visual C# Tutorials!"); System.Console.ReadKey();

This can be tedious if you will be repeatedly typing this over and over. Fortunately, we can import namespaces. We can use using statements to import a namespace. Here's the syntax: using namespace;

This is an example of a using statement which imports a namespace and instructs the whole program that you are using the contents of that namespace. So instead of using the following line of code: System.Console.WriteLine("Hello World!");

We can simply write the following code when we imported the System namespace: Console.WriteLine("Hello World");

Using statements which imports namespaces are typically placed at the topmost part of your code. Here is the updated version of Example 2 which imports the System namespace. using System; namespace MyFirstProgram { class Program { static void Main() { Console.WriteLine("Welcome to Visual C# Tutorials!"); Console.ReadKey(); } } }

Example 3 - Importing a Namespace You can still use the full name of a class though if there are other class which has the same name. Namespaces will be discussed in greater detail in another lesson.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You are now familiar with the workflow of creating as well as the basic structure and syntax of a simple C# program. The next lessons will sharpen you knowledge of C# even further.

Using the IntelliSense Perhaps one of the most important feature of the Visual Studio family is the IntelliSense. IntelliSense serves as an autocompletion tool as well as a quick reference for classes, methods, and many more. I remember using an old IDE for C++ and I have to memorize the neccessary codes I have to use. With IntelliSense, I learn as I type because you actually see a brief description of each components describing how to use them. IntelliSense is activated the moment you type a letter in the Code Editor. Type the following code inside the Main method of the program. System.Console.WriteLine("Welcome to Visual C# Tutorials!");

Typing the first letter of the statement automatically activates IntelliSense.

IntelliSense gives you a list of recommendations with the most relevant one on the first of the list. You can press tab to accept the selected recommendation. Typing a dot will bring you another list of recommendations. The list is based on all the components that are contained inside the preceding namespace.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

If you stay the selection for a short amount of time, the description about the selected item will show up. This allows you to learn what each item does without going to the full documentation. As you type the code, the list is narrowed down. For example, typing the letter W make IntelliSense to only show items with W's in it.

Typing more letters will narrow the list even further.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

If IntelliSense cannot find something that matches what you are typing, then nothing will be shown. You can press Ctrl while a list is shown to make the list transparent. It's useful when the list box is blocking some of your codes. When working with methods with multiple overloads(versions), you can use the arrow heads to see all the possible overloads of the method.

You will also see the different parameters required by the method and their individual descriptions. Methods and parameters will be discussed in a later lesson. IntelliSense is such a great feature, and for every release of Visual Studio, IntelliSense becomes even more intelligent in suggesting codes for you. It is one of the time-saving tools Visual Studio offers.

Troubleshooting Errors Most of the time, errors are encountered when creating a program. Almost all of the programs you see today suffered at least one error. Errors can be devastating if not fixed immediately. In C# there are 3 types of errors you can encounter. 





Compilation Error - This type of error prevents you from compiling and executing your program. Such errors include syntax errors which means that you violate the rule of the programming language. Another compilation error is using something that does not exist or has not been created yet. Missing files or incomplete information about the project and solution may also cause compilation error. Compilation error will also occur when the program cannot be ran because another process is already using it. Compilation errors are the easiest to fix using Visual Studio tools. Logic Error - This type of error changes the proper logic of the code which defines how the program will behave. This is the hardest error to fix as you need thorough testing to discover this type of error. An example of a logic error is a program that is suppose to add 2 numbers but subtracts them instead. The cause might be the programmer typed a wrong arithmetic symbol during the coding of the program. Exception - This type of error occurs while the program is running. A typical event where this error can occur is if the user provides an invalid input to the program that the program cannot process. Another example is when the program accesses a null (nothing) value.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Visual Studio and Visual C# Express has tools for finding and fixing these types of errors. When typing in the Code Editor, one of the features of these IDE's is to detect possible errors before you even compile the program. Codes that may cause compilation errors have red squiggly lines below them.

Hover your mouse to these squiggly lines to see a description of the error. You might encounter green squiggly lines. They indicate warnings in code but will still allow you to run the program. An example is when you declare a variable and never use it within the program (variables will be discussed later).

Logic errors and exceptions can be handled using the debugging tools and exception handling which will be discussed in a later lesson.

The Error List Window The Error List window allows you to see all the errors and warnings of the current solution. To open the Error List window, go to View > Other Windows > Error List. By default, the Error List window is located at the bottom area of the IDE. Like the other windows, you can unpin the Error List to enable auto-hide by clicking the pin beside the close button.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will see the errors and warning reported here whenever errors are detected in your program.

You can see the number of errors and warnings as well as some messages regarding the solution. The Error List consist of multiple columns that provide you in-depth details about the errors. Column Description Description The description of the message File The file where the error is located. Line The line number of the error within the file. Column The column or the horizontal position of the error within the line.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Column Description Project The project name where the error is located. Figure 1 - Error List Window Columns If you run the program with errors, you will be presented with an error window.

Do not check the check box located below this window because this window is useful for notifying us that errors exist when we run the code. Clicking Yes will run the previous version of the program that has no errors. Clicking No will halt execution of the program so that you fix the errors presented in the Error List window. Another great feature of the Error List window is it automatically brings you to the part of your solution that has the error. Simply click an error listed in the Error List and you will be brought to the part of solution where the error exists.

Understanding Errors and Fixing Them Once all the errors are listed in the Error List window, you need to be able to understand what each error means so you can fix them. The following common errors together with their solution are listed below. The name 'sample' below will be substituted with a different name depending on the error you encounter. Error ; expected The name 'sample' does not exist in the current context.

Description Solution You forgot to add a semicolon at Add a ; to fix this error. the end of a statement. It simply means that the name Delete it or declare it in your 'sample' was not declared or code. does not exist in your code.

Only assignment, call, increment, decrement, and new It means that the code is not a object expressions can be used valid C# statement. as a statement. Use of unassigned local The variable 'sample' is not

COMPILED BY:

Delete the statement. Assign a value to the variable

Bsc ABDULRAHIM ALI ATHUMAN

Error variable 'sample'

Description assigned with an initial value.

Solution before the statement that calls or use it. You need to create a class or The type or namespace name It means that there is no type or namespace named 'sample', or 'sample' could not be found (are namespace declared which has a add a reference to your you missing a using directive or name of 'sample' program and import with a an assembly reference?) using statement. This means that the method 'MyMethod()' which is supposed 'MyMethod()': not all code Be sure that all the paths of to return value, does not return a paths return a value code will return a value. value on all the paths of the code. Try using casting or use This means that a variable of conversion methods. If it still Cannot implicitly convert type type2 cannot be converted to yields an error, then a 'type1' to 'type2' type1 without using a cast or conversion for those types is conversion methods. currently not possible. Figure 2 - Some error messages and how to fix them Don't worry if some terms are not clear to you as they will be explained in later chapters. Use the Edit List window's feature of automatically bringing you to the location where the error exists so you can easilly fix it.

Comments When writing code, you might want to add some text that will serve as a reminder or a note for you or for anyone who will read your code. In C# (and most programming languages), you can do that using comments. Comments are ignored by the compiler and are not part of the actual C# code. Their main purpose is to make it easy for you or to anyone who reads your code to determine the role of your code inside your program. Suppose you want to describe what a particular code is going to do, then you can place a comment above or beside it. It is also used for documentation purposes. Here is an example of a program with a comment: 1 namespace CommentsDemo 2 { 3 class Program 4 { 5 public static void Main(string[] args) 6 { 7 // This line will print the message hello world 8 System.Console.WriteLine("Hello World!"); 9 } 10 } 11}

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Example 1 - Using a Comment Line 7 shows an example of a single line comment. There are two types of comments, single line comments and multiline comments as presented below: // single line comment /* multi line comment */

Single line comments as the name implies, are comments good for one line only. A single line comment starts with // and everything to its right will be part of the comment. Single line comments are often placed above or to the right of a single line of code. This comments are ideal for describing the functionality of a single line of code. If your comment is longer and requires multiple lines, use the multiline comment. A multiline comment starts with /* and ends with */. Everything between /* and */ will be considered comments. This type of comment is useful for adding details about the program at the source code's header or any long comments that spans multiple lines. There is another type of comment which is called XML comment. It is represented by three slashes (///). It typically functions as a single line comment but it is commonlly used for creating automatic documenation for your code. You will learn more about XML comment and how to use it in a separate lesson.

Escape Sequences Escape sequences are character combinations starting with a backslash (\) and followed by a letter or digits inserted in a string literal to produce a modified output. For example, to produce a newline when outputting a string, we can use the \n escape sequence. System.Console.WriteLine("Hello\nWorld!"); Hello World

You can see that once the compiler encounters the \n character, it puts the cursor of the output to the next line and continue showing the output of the rest of the string. In fact, the WriteLine() method automatically adds \n to the end of the string so: System.Console.WriteLine("Hello World!");

is equivalent to: System.Console.Write("Hello World!\n");

The Write() method functions the same as the WriteLine() except that it doesn't add a newline to the end f the string. COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The following table shows a list of escape sequences and their corresponding effect: Escape Sequence Output \' Single Quotation mark \" Double quotation mark \\ Backslash \0 Null \a Alert(beep sound) \b Backspace \f Form Feed \n New Line \r Carriage Return \t Horizontal Tab \v Vertical Tab \u Prints a unicode character Figure 1 We used the \ when indicating the start of an escape sequence. Since the backslash gives special meaning to a string literal, we can print a backslash by using the \\ escape sequence. System.Console.WriteLine("We can print a \\ by using the \\\\ escape sequence."); We can print a \ by using the \\ escape sequence.

The \\ is also useful if you want to output, for example, a file path. System.Console.WriteLine("C:\\Program Files\\Some Directory\\SomeFile.txt"); C:\Program Files\Some Directory\SomeFile.txt

Since we use the " character to enclose a string, we can print a double quotation using the \" escape sequence. System.Console.WriteLine("I said, \"Motivate yourself!\"."); I said, "Motivate yourself!".

We can also use the \' to print single quotation marks ('). System.Console.WriteLine("The programmer\'s heaven."); The programmer's heaven.

Tabs can be made by using the \t escape sequence. System.Console.WriteLine("Left\tRight"); Left Right

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The \r escape sequence causes a carriage return which puts the cursor to the beginning of the current line. Once the cursor is in the beginning of the line, it overwrites any characters it encounters with those following the \r. System.Console.WriteLine("Mitten\rK"); Kitten

On the example above, the letter K is after the \r. When the \r is encountered, the cursor is brought to the beginning of the line and K overwrites the letter M producing the new word. To print any unicode character, you can use the \u escape sequence. To use the \u, write the 4digit hexadecimal value of the unicode symbol right after the escape sequence. For example, if you want to print the copyright © symbol, you can use the \u00A9 escape sequence since 00A9 is the hexadecimal value for copyright symbol. System.Console.WriteLine("\u00A9"); ©

For a list of hexadecimal values for unicode, go to the link below: http://www.ascii.cl/htmlcodes.htm If the compiler finds an invalid escape sequence, an error will occur. One of the most common errors is when forgetting to use the \\ when a programmer wants to print a slash. As a result, the compiler interprets the very next letter following the \. The other escape sequences are rarely used and is therefore not discussed in this lesson.

String Verbatim String Verbatim allows you to ignore escape sequences and makes writing strings more natural and readable. When using escape sequences in string literals, you sometimes make a mistake of typing \\ for the "backslash" and type \ instead. This will produce an error because the compiler will think that you are starting an escape sequence and it will read the next character after the \ and process it. If it doesn't find a matching escape sequence, then it will issue an error. Consider the following example: System.Console.WriteLine("I want to have a cat\dog as a birthday present."); //Error

Although it would be proper to use the / instead as in "cat/dog" in the example above, I intentionaly used backslash for demonstration-this is not literature lesson after all. The compiler will issue an error and tell you that it did not recognize the escape sequence \d clearly because no such escape sequence exist. It will be worse if the next character following the backslash is something that the compiler can recognize such as \n as seen in the following example: System.Console.WriteLine("Answer with yes\no:");

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Answer with yes o

Using String Verbatim to Ignore Escape Sequences We use string verbatim in certain situations where you don't want your backslashes to trigger an escape sequence. The syntax for string verbatim is simple. Just prefix the string literal with the @ symbol. System.Console.WriteLine(@"I want to have a cat\dog as a birthday present."); I want to have a cat\dog as a birthday present.

String verbatim is commonly used when you are trying to output directories as string. Because directories contain a lot of backslashes, it would be justifiable to use string verbatim rather than using double backslash. System.Console.WriteLine(@"C:\Some Directory\SomeFile.txt"); C:\Some Directory\SomeFile.txt

If you want to print double quotations, simply use two double quotations. System.Console.WriteLine(@"Printing ""double quotations""..."); Printing "double quotations"...

Avoid using string verbatim and escape sequences at the same time as it will also print the escape sequences in the output.

Using String Verbatim to Preserve Formatting of Strings You can also use string verbatim to print multiline strings without the user of \n escape sequence. For example, if we are to print the following message: C# is a great programming language and it allows you to create different kinds of applications.

Then we have to write it in C# as follows: System.Console.WriteLine("C# is a great programming language and\n" + "it allows you to create different\n" + "kinds of applications.");

Notice the use of \n at the end of each line. This is to seperate them in different lines as shown in the output sample of the message. The string was also divided into three just so we can save space. The + operator is used to combine the strings so that the three string literals will be combined into one. With string verbatim, we can make our lives easier when printing multiple lines of text. System.Console.WriteLine(@"C# is a great programming language and

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

it allows you to create different kinds of applications.");

Notice that we with string verbatim, we can use one continuous string and it will be printed exactly the same as how it was typed in the editor. That's why the second and third lines has no indention because if we indent them, the output will also be indented. Be carefull to use string verbatim. Although it is useful in many circumstances, you should stick to the usual way of printing strings with escape sequences. Only use string verbatim when neccessary.

Variables A variable is basically a storage in the computer's memory where you can put a value that will be used by your program. Picture it as a container that holds your data. The contents of the container can be removed or changed anytime. The variable has a name, which identifies it among other variables and allows you to access the value of the variable. It has an address which determines where in the memory it resides. It has a value which is either assigned by the user or a result of a calculation although a variable can have a value of null or nothing. A variable has a data type, which signifies what kind of data the variable contains. A variable has a lifetime which determines how long in the program the variable is usable. And finally, a variable has scope which tells you where in a program the variable is available for use. We use variables as temporary storage of data or values. When creating programs, we need means of storing results, values, or input data from user. This is the role of the variable. The variable got its name from the term variability which means changing or don't have a consistent state. This is because we can assign and change the value of a variable whenever it is neccessary. Variables are temporary and will only be usable when the program is running. When you close your program, values stored in variables are erased. The name of a variable is called an identifier. The variables content is accessed or inserted using its identifier. When naming variables in C#, there are some rules you must follow.    

A variable should start with an alphabet (a-z or A-Z) It cannot contain odd characters such as #, ?, ^, $. You cannot use any of the reserved words in C# as names for your variables. A variable name cannot contain spaces.

Variable names are also case-sensitive. C# is a case-sensitive language, which means, a and A are two different characters. Two variables named myNumber and MyNumber are two different variables because the first one starts with 'm' and the other one starts with 'M'. You cannot declare a variable which is exactly the same as the name of another variable within the same scope. Scope means the block of code a variable is available for use. You will learn more about scope in a later lesson.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

A variable has a data type which is the format or kind of data that it is expected to hold. Data type is used to allow a computer to describe what kind of data it holds and what operations you can do to it. Most common data types are int, double, string, char, float, decimal and a lot lot more for storing different kinds of data depending on the situation. For example, if you are expecting a variable to hold a whole number, you will give it a type of int. If you are expecting a variable to hold string literals or message, you would want to give it a data type of string. More complex data types can be made in C# by making your own classes or structures.

Simple Types Simple types are data types which include numbers, characters and strings, and boolean values. They are called primitive data types in other languages because you use them to build complex types such as classes and structures. Simple types contain clearly defined set of values and can store a fixed range of data. They are the fundamental building blocks of your application. Each simple type is mapped to a .NET type thanks to .NET's Common Type System. It makes data types from different languages to be considered as one by .NET. For example if you use the int data type, you are actually using the .NET type System.Int32. The following table shows some of the available simple types that you can use for storing numbers. Type .NET Type Value Range sbyte System.SByte Integer between -128 and 127 byte System.Byte Integer between 0 and 255 short System.Int16 Integer between -32768 and 32767 ushort System.UInt16 Integer between 0 and 65535 int System.Int32 Integer between -2147483648 and 2147483647 uint System.UInt32 Integer between 0 and 4294967295 Integer between -9223372036854775808 long System.Int64 and 922337203685477807 ulong System.UInt64 Integer between 0 and 18446744073709551615 Figure 1 You might notice the u at the beginning of some data types such as ushort. It means that the number it will store is "unsigned" and you can only store positive numbers(and 0) in them. They store larger values as a reward for forbidding negative values. Note that byte is the unsigned version of sbyte but it was not named usbyte. The next table shows simple types that can store "floating numbers" or numbers with fractional part or decimal points such as 1.5.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Type .NET Type Approximate Range Precission float System.Single ±1.5E-45 to ±3.4E38 7 digits double System.Double ±5.0E-324 to ±1.7E308 15 - 16 digits (-7.9 x 1028) / (100 to 28) to decimal System.Decimal 28 - 29 significant digits (7.9 x 1028) / (100 to 28) Figure 2 We used the shorthand version of scientific notations. Instead of writing 1.5 x 10-45, we wrote 1.5E-45 instead. There are other types of simple data types which are used for storing non-numerical data. They are shown in Figure 3. Type

.NET Type

Allowed Values Single Unicode character, stored as an integer char System.Char between 0 and 65535 bool System.Boolean true or false string System.String A sequence of characters Figure 3 The char datatype is used for storing single unicode character. Characters must be enclosed by single quotation marks ('a'). The bool datatype can store true or false which is used mostly when making decisions in a program. The string is used for storing a sequence of characters such as a message. Values stored in string must be wrapped between quotation marks ("message") so it can be distinguish as a string by the compiler.

Using Variables Variables in C# are containers inside the computer's memory where you can place the data you need for your program. The term "variable" got its name from the fact that variables represent values that change. The data stored in these variables have different types called data types which determines the type of data a variable can store. For example, a variable with an int data type can only store whole numbers and a variable with a string data type can store string literals. Example 1 demonstrates how you can declare and assign values to the variables. 1 using System; 2 3 namespace VariableDemo 4 { 5 class Program 6 { 7 public static void Main() 8 {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37}

//Declare variables int num1; int num2; double num3; double num4; bool boolVal; char myChar; string message; //Assign values to variables num1 = 1; num2 = 2; num3 = 3.54; num4 = 4.12; boolVal = true; myChar = 'R'; message = "Hello World!"; //Show the values of the variables Console.WriteLine("num1 = {0}", num1); Console.WriteLine("num2 = {0}", num2); Console.WriteLine("num3 = {0}", num3); Console.WriteLine("num4 = {0}", num4); Console.WriteLine("boolVal = {0}", boolVal); Console.WriteLine("myChar = {0}", myChar); Console.WriteLine("message = {0}", message); } }

Example 1 - Variables in Action num1 = 1 num2 = 2 num3 = 3.54 num4 = 4.12 boolVal = true myChar = R message = Hello World!

Declaring Variables Lines 8-14 declared variables with different data types and names. We declare variables so the program will know them and what data each of them can contain. It's like introducing those variables to the program. Always keep in mind that you need to declare variables first before you can use or assign values to them. int num1; int num2; double num3; double num4; bool boolVal; char myChar; string message;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

When declaring variables, you need to indicate the data type followed by the name of the variable terminated by semicolon. Declaration of variables is simply called declaration. The following is the syntax of declaring a variable: data_type identifier;

The date_type is the data type of the variable such as int, double or char. The identifier is the valid name of the variable and is used to access the variables content or add a new value to it. You can also declare multiple variables with the same data type in just one line. It uses the following syntax: data_type identifier1, identifier2, ... indentifierN;

Take a look at the following example: int num1, num2, num3, num4, num5; string message1, message2, message3;

The above declaration statements declares five integer variables and three string variables. We simply indicate the data type and a comma-separated list of identifiers.

Naming Variables The identifier must start with an alphabet or an underscore, followed by alphabet or numbers. You cannot use special characters such as #, %, &, or start the identifier name with a number such as 2numbers. Identifiers can't contain spaces. As a workaround for multiple word names, you can use underscore(_) instead of space (you can't use the - sign). The following are examples of valid variable names. num1 num2 name

myNumber myChar counter

studentCount average sum

total amountDue isLeapYear

first_name last_name color_of_car

_minimum _maximum _age

The following are examples of invalid names for identifiers. 123 123abc my number

#numbers# $money this&that

#ofstudents first name last name

1abc2 ty.np 1:00

If you look at the examples of valid variable names, you will notice a convention used when naming them. Camel Casing is a naming practice which states that, the first letter of the first word should be a small letter. Each succeeding letters are small letters. For multiple-word variables, each succeeding word must have their first letter capitalized. For example, the identifier myNumber contains the words "my" and "number". Notice that the first letter of the word number in the indentifier is captialized. Another example is numberOfStudentsWhoGraduated which is quite a long name that uses camel casing. Notice how

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

each words after the first word has their first letter capitalized. More naming conventions will be introduced to you as we progress to future lessons.

Variable Scope Notice that the variables are declared inside the block of the Main method. This limits these variables to be only accessible or usable inside the Main method. This is called scope which determines where in the code, variables can be used. Once the program reaches the end of the Main method, these variables go out of scope and becomes unusable while the program is running. There are more types of scopes. You will learn more about scopes in a later chapter. Determining the scope of variables is important so you can know where in your code can you use those variables. Another reason is that, two or more variables within the same scope cannot have an exact same name or identifier. The following will produce an error: int num1; int num1;

This is a typical error and you will get an error message when compiling saying "A local variable named 'num1' is already defined in this scope". But because C# is case sensitive, you can provide the same names of variables as long as they have different cases. The following three variables are actually three different variables and will be accepted by the compiler. int num1; int Num1; int NUM1;

Initializing Variables You can assign values to variables immediately after they have been declared in the program. This is called initialization. The following is the basic syntax of intializing a variable with a value. data_type identifier = value;

For example: int myNumber = 7;

You can also initialize multiple variables. Simply seperate them with a comma. data_type variable1 = value1, varaible2 = value2, ... variableN, valueN; int num1 = 1, num2 = 2, num3 = 3;

It is important to know the difference of declaration and initializaiton. Declaration simply declares the method by specifying the data type and the name of the identifier. If you try to use an undeclared variable, then you will receive an error message "Use of unassigned local variable 'myVariable'" where myVariable is the name of the unassigned variable. Initialization is similar

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

to declaration but values are assigned to the declared variables. This gives a variable an "initial value" hence the term initialization.

Assigning Variables with Values Assigning a value to a variable is placing a value inside the variable. Think of it as putting some contents to an empty container. When assigning variables with a value, you use the following syntax. variable = value;

You indicated the name of the variable followed by the assignment operator which is represented by the = sign then followed by the value to be assigned to the variable. The left of the assignment operator is often called an L-Value (left value) while the right side of the assignment operator is often called R-Value (right value). Lines 19-25 of Example 1 assigns values to each variables that we have declared. num1 = 1; num2 = 2; num3 = 3.54; num4 = 4.12; boolVal = true; myChar = 'R'; message = "Hello World!";

Note that we cannot assign values to variables that has not been declared yet. You can only assign values to variables that are valid and can be accepted by the variable depending on its data type. For example, num1 and num2 are both declared int so they can only accept whole numbers as values. boolVal was declared bool so it can only accept either values true or false. message was declared string so it can accept a string literal. Failing to assign proper values can lead to errors. You will learn in a later lesson that some datatypes are related.

Format Placeholders You noticed the new version of the WriteLine() method (lines 26-32). It now accepts two arguments. Arguments are the information needed by the method to supplement its job. Arguments are seperated by a comma. The first argument accepted by WriteLine() is the formatting string and the second one is the value to be used by the formatting string. If you look closely, the formatting string has {0}. They are called format placeholders. This will be substituted by the value of the next argument. For example, the placeholder {0} means that it will be replaced by the value of the first argument following the formatting string. The new version of WriteLine method can actually accept any number of arguments, with the first one being the string containing the format placeholders, and the following arguments are the values that will substitute the placeholders. For example, the following uses 4 placeholders. Console.WriteLine("The values are {0}, {1}, {2}, and {3}.", value1, value2, value3, value4);

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Format placeholders start with index 0. The number of placeholders must match the number of arguments following the formatting string. For example, if you have four placeholders as shown above, then you must provide four values right after the formatting string. The first placeholder {0} in the formatting string will be substituted by the second argument. The second placeholder {1} will be substituted by the third argument, and so on. It might be hard for beginners to understand this concept at first, but you will look at more examples of these in later lessons.

Constant Variables Constant variables, or simply constants, are variables whose value cannot be changed once initialized. Given that fact, constants can only do initialization since forgetting to initialize a constant will produce an error. Constants must be assigned with an initial value, and after that, the value can never be changed at runtime. To declare a variable as constant, simply use the const keyword. Constant's name should be in all caps as part of C#'s naming convention. It is not required but it allows you to easily identify which are the constants. Here's the syntax for defining a constant. const data_type identifier = initial_value;

Heres an example of using a constant. namespace ConstantsDemo { class Program { public static void Main() { const int NUMBER = 1; NUMBER = 10; //ERROR, Cant modify a constant } } }

You can see that assigning a value to a constant once it has been declared leads to an error. Another thing to note is that you cannot initialize constants with variables who's value is not known during compilation. For example, doing the following produces an error. int someVariable; const int MY_CONST = someVariable;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You might be wondering why do we need to use constants. If you are certain that a value will never change during runtime, make the variable constant. This will add a little bit of performance improvement to your program.

Implicit Conversion Implicit conversion of variables is a kind of conversion that is automatically done by the compiler. A variable of one data type can be implicitly converted to another datatype provided that its content can be handled by the type it will be converted to. For example, a byte datatype can hold values from 0 to 255. You convert this variable to an int type like this: byte number1 = 5; int number2 = number1;

We initialize the value of number1 to 5 and use its value to initialize number2. The int variable number2 can hold the byte value 5 because int data type can hold the value 5 without any problems as it falls within the range of values an int can hold. Therefore, number1 which is a byte, is implicitly converted to number2 which is an int. What if we switch the types of the two? int

number1 = 5;

byte number2 = number1;

This time, you will receive an error. Even though the value 5 of the int variable number1 falls in the range of values a byte can hold (1 - 255), the byte uses less memory than the int. The byte data type contains 8 bits or 8 digits of binary value while int contains 32 bits or binary digits. A binary number is a number that is composed of 0's and 1's. For example, we see the number 5 as 5 but the computer interprets it as a binary number 101. So when we store 5 in a byte variable, it will be represented as this: 00000101

And if we place it in an int, the binary representation of it will be as follows: 00000000000000000000000000000101

Therefore, placing an int value to a byte variable is like trying to shoot a bowling ball in a golf hole. You can still assign a byte variable with an int value by using explicit conversion which is discussed in the next lesson. Another thing to take note about is that you cannot convert floating point numbers or numbers with decimal part implicitly into a number that accepts a whole number such as int. This is because of the reason that you will lose the fractional part of the floating-point value. double number1 = 5.25; int number2 = number1; //Error

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can also convert a char into a ushort because these two types has the same range of values they can store. Although each of them are interpreted differently by the compiler. The char is interpreted as a character and a ushort is interpreted as a number. char charVar = 'c'; ushort shortVar = charVar; Console.WriteLine(charVar); Console.WriteLine(shortVar); c 99

Below is a table showing the numeric conversions the compiler can do implicitly: Source Type Can Safely Be Converted To byte short, ushort, int, uint, long, ulong, float, double, decimal sbyte short, int, long, float, double, decimal short int, long, float, double, decimal ushort int, uint, long, ulong, float, double, decimal int long, float, double, decimal uint long, ulong, float, double, decimal long float, double, decimal ulong float, double, decimal float double char ushort, int, uint, long, ulong, float, double, decimal Another thing to note, often, there is an ambiguity to what would be the type of a data. For example, how can we know if number 7 is int, uint, long, or ulong? We can append characters to the end of the number like this: uint number1 = 7U; long number2 = 7L; ulong number3 = 7UL;

By default, the compiler will treat it as an int if no character is appended to the number. Also note that the casing doesn't matter and you can use u,l and ul. By default, a number with a decimal point is considered as double. You can indicate the it is a float by using the F character, and M if you want to treat it as a decimal. double number1 = 1.23; float number2 = 1.23F; decimal number3 = 1.23M;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Explicit Conversion Explicit conversion lets you force the program to convert a data into another data type if it doesn't support implicit conversion. Explicit conversion has a tendency of losing or resulting to a modification of value so be cautious when using this type of conversion. We do an explicit conversion in C# by doing a cast. Casting is just another term for explicit conversion and it follows the following syntax: datatypeA variableA = value; datatypeB variableB = (datatypeB)variableA;

datatypeA is the type of the source data. datatypeB is the destination type. When doing a cast, we enclosed the target data type between parenthesis followed by the variable of another data type that we are going to convert. For example, we saw that you cannot implicitly convert an int into a byte. It's like downgrading the int variable. But we can use casting to have a successful conversion. int number1 = 5; byte number2 = (byte)number1;

If you compile this code, you will not receive an error. We have "downgraded" an int data into a byte data. As I have said earlier, there are events where you can lose the originality of data you are converting. An example is when converting a floating-point number such as double in an int which can only hold whole numbers. double number1 = 5.25; int number2 = (int)number1; Console.WriteLine(number2); 5

The code above will give as an output of 5 instead of 5.25. The fractional part or the part after the decimal point is lost because int data type cannot hold it. Another thing to keep in mind is if you are converting a variable containing a value which is not within the range of the values a target variable can hold, then odd results will be encountered. Consider the following code. int number1 = 300; byte number2 = (byte)number1; Console.WriteLine("Value of number2 is {0}.", number2); Value of number2 is 44.

The output below shows that converting the int value 300 into byte resulted to 44. Byte can only hold a value 0 to 255. So why did we get 44 instead of 300? This has something to do with the number of bits each type can hold. byte can hold 8 bits (0's or 1's) and int can hold 32. If we look at the binary representation of the two values, we can see why we got 44.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

300 = 00000000000000000000000100101100 255 = 11111111 44 = 00101100

The representation above shows that the max value of byte which is 255 takes up eight bits (11111111) so only the first eight bits of the int value is transfered to the byte variable which are (00101100) or 44 in decimal representation. Fitting a data into a variable that cannot hold the value results to an overflow. Overflows can also occur if the result of a methematical expression is assigned to a variable that cannot hold a result. This is called arithmetic overflow. byte sum = (byte)(150 + 150);

Even though we will lost some data because of the conversion, the compiler still accepts our code. To make the program issue an error when an expression results to an overflow, you can use the checked keyword. int number1 = 300; byte number2 = checked((byte)number1); Console.WriteLine("Value of number2 is {0}.", number2); Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow ...

The program will throw a System.OverflowException which simply means that an overflow was detected. This will prevent the program to progress.

Conversion Using the Convert Class The .NET Framework has a static class available that can be used for converting values from one type to another. The Convert class has some methods that can be used to convert to different target datatypes. You must import the System namespace before using the Convert class. Below shows the table of those methods Command

Result

Convert.ToBoolean(val) val converted to bool Convert.ToByte(val) val converted to byte Convert.ToChar(val) val converted to char Convert.ToDecimal(val) val converted to decimal Convert.ToDouble(val) val converted to double Convert.ToInt16(val) val converted to short Convert.ToInt32(val) val converted to int Convert.ToInt64(val) val converted to long Convert.ToSByte(val) val converted to ushort Convert.ToSingle(val) val converted to float

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Command Convert.ToString(val) Convert.ToUInt16(val) Convert.ToUInt32(val) Convert.ToUInt64(val)

Result val converted to string val converted to ushort val converted to uint val converted to ulong

Figure 1 - Conversion Methods The following program shows you an example of converting variables. double x = 9.99; int convertedValue = Convert.ToInt32(x); Console.WriteLine("Original value is: " + x); Console.WriteLine("Converted value is: " + convertedValue); Original value is: 9.99 Converted value is: 10

The value of val can be any data type but make sure that it can be converted to the target data type. If these commands cannot handle the conversion, then the compiler will tell you about this by issuing an error.

Expressions and Operators Modern programming languages has operators which is one of the common elements of a programming language. C# offers different operators like mathematical operators, assignment operators, and comparison operators. There are different kinds of operators in C# and you might not be familiar to some of them. Basic operators are what we use for mathematical calculations such as addition and substraction. Then there are more complex ones use for combining two comparison expressions. There are three types of operators in C#:   

Unary - requires a single operand Binary - requires at least two operands Ternary - requires three operands

The different kinds of operators in C# that this section will discuss includes the following:     

Mathematical Operators Assignment Operators Comparison Operators Logical Operators Bitwise and BitShift Operators



Mathematical Operators

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

 

C# has available operators for use in mathematical calculations. By combining operators and operands, we have an expression which is how C# makes calculations. Here is a table of available mathematical operators in C#.

Operator Category Example Expression +

Binary

var1 = var2 + var3;

-

Binary

var1 = var2 - var3;

*

Binary

var1 = var2 * var3;

/

Binary

var1 = var2 / var3;

%

Binary

var1 = var2 % var3;

+

Unary

var1 = +var2;

-

Unary

var1 = -var2

Result var1 is assigned with the sum of var2 and var3. var1 is assigned with the difference of var2 and var3. var1 is assigned with the product of var2 and var3. var1 is assigned with the quotient of var2 and var3. var1 is assigned with the remainder resulted from the division of var2 and var 3. var1 is assigned with the value of var2 var1 is assigned with the value of var2 multiplied by -1.

Figure 1 - Mathematical Operators 



The example above uses numeric types. But using this on other types such as string can have different results. Likewise, adding two char will result on the compiler converting their value to their respective numerical equivalents. If the + operator is used with string data, it will concantenate the two strings and combine them into one. Another set of operators in C# are the increment and decrement operators. These operators increases or decreases the value of a variable by 1. This operators are often used for looping.

Operator Category Example Expression ++

Unary

var1 = ++var2;

--

Unary

var1 = --var2;

++

Unary

var1 = var2++;

--

Unary

var1 = var2--;

Result var1 is assigned the value of var2 + 1. var2 is incremented by 1. var1 is assgine the value of var2 - 1. var2 is decremented by 1. var1 is assigned the value of var2. var2 is incremented by 1. var1 is assigned the value of var2.. var2 is decrementday by 1.

Figure 2 - Increment and Decrement Operators

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN





Note that the position of the two operators determines the effect of the calculation. If the operator is a prefix to the variable, the incrementation or decrementation took place first before being assigned to var1. Contrast to when you place it at the end of var2, the value assigned to var1 is the value of var2, the incrementation or decrementation for var2 will happen after it's value is assigned to var1. We will now try what we learned by creating a new program that tests the mathematical operators of C#.

using System; 1 public class Program 2 { 3 public static void Main() 4 { 5 //Variable declarations 6 int num1, num2; 7 string msg1, msg2; 8 9 //Assign test values 10 num1 = 5; 11 num2 = 3; 12 13 //Demonstrate use of mathematical operators 14 Console.WriteLine("The sum of {0} and {1} is {2}.", num1, num2, (num1 15+ num2)); 16 Console.WriteLine("The difference of {0} and {1} is {2}.", num1, 17num2, 18 (num1 - num2)); 19 Console.WriteLine("The product of {0} and {1} is {2}.", num1, num2, 20 (num1 * num2)); 21 Console.WriteLine("The quotient of {0} and {1} is {2:F2}.", num1, 22num2, 23 ((double)num1 / num2)); 24 Console.WriteLine("The remainder of {0} divided by {1} is {2}", num1, 25num2, 26 (num1 % num2)); 27 28 //Demonstrate concatenation on strings using the + operator 29 msg1 = "Hello "; 30 msg2 = "World!"; 31 Console.WriteLine(msg1 + msg2); } }

Example 1      

The sum of 5 and 3 is 8. The difference of 5 and 3 is 2. The product of 5 and 3 is 15. The quotient of 5 and 3 is 1.67. The remainder of 5 divided by 3 is 2 Hello World!

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The program demonstrates the expected results for each expressions. Again, we use the overloaded version of the Console.Writeline() to make it easier to write and format. There is one odd thing you might notice when dividing the two integers. If we divide two integers, it will yield another integer. That would drop out all the fractional part of the result and give us only a whole number. In line 22, we convert at least one of the operand to double to get the right result. Then we format the result to only show 2 decimal places using {2:F2}. F means fixed and 2 means the number of decimal places to include. Note that the number is rounded. The statement is too long so we split it into two lines. C# ignores newlines, tabs and white spaces so there is no problem about this. 

Line 29 shows string concatenation using the + operator on strings. When we used the + operator for the two string data, we get a different result. Adding "Hello " and "World!" gives us "Hello World!". Take note of the extra space added to the end of the first word. Omitting this will also omit the space between the two words in the final output.

Assignment Operators 

There is another set of operators in C# and they are called assignment operators. They are use to modify the value of the left operand depending on the right operand. The table shows assignment operators and their functionality.

Operator Example Expression Result = var1 = var2; var1 is assigned a value of var2. var1 is assigned the value that is the sum of += var1 += var2; var1 and var2 var1 is assigned the value that is the difference of -= var1 -= var2; var1 and var2 var1 is assigned the value that is the product of *= var1 *= var2; var1 and var2. var1 is assigned the value that is the result of /= var1 /= var2; dividing var1 by var2 var1 is assigned the value that is the remainderr %= var1 %= var2; when var1 is divided by var2 Figure 1 - Assignment Operators 



The += can also be used for concatenating strings. The table above shows that the assignment operators are actually a short hand of doing calculations on two operands. Consider var1 += var2, the original form of it would be var1 = var1 + var2. It would be more efficient to use assignment operators specially when you have very long variable names. The following program shows how to use assignment operators and their effect on variables. Since the concept for each of the assignment operators is the same, I'm not going to show all of them.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

1 using System; 2 3 public class Program 4 { 5 public static void Main() 6 { 7 int number; 8 9 Console.WriteLine("Assigning 10 to number..."); 10 number = 10; 11 Console.WriteLine("Number = {0}", number); 12 13 Console.WriteLine("Adding 10 to number..."); 14 number += 10; 15 Console.WriteLine("Number = {0}", number); 16 17 Console.WriteLine("Subtracting 10 from number..."); 18 number -= 10; 19 Console.WriteLine("Number = {0}", number); 20 } 21}

Example 1      

Assigning 10 to number... Number = 10 Adding 10 to number... Number = 20 Subtracting 10 from number... Number = 10

The program uses three of the assignment operators. First, we declared a variable that will hold the value for manipulation. We then assign a value of 10 using the = operator. We added 10 to the number by using the += operator. Finally, we subtracted 10 from the number using = operator.

Comparison Operators C# has comparison operators which are used when comparing values or references of variables. These operators yield boolean results. Values yielded by comparison expressions are either true if the comparison is in fact true, and false if the comparison is false. These comparison operators are commonly used in if statements and testing if the loop should continue or stop. The comparison operators are the key to make your programming decide and think. Below shows a list of comparison operators in C#. Operator Category ==

Binary

COMPILED BY:

Example

Result var1 is assigned true if var2 is var1 = var2 == var3 equal to the value of var3,

Bsc ABDULRAHIM ALI ATHUMAN

Operator Category

!=

Binary




Binary

=

Binary

Example

Result

false otherwise var1 is assigned true if var2 is not var1 = var2 != var3 equal to the value of var3, false otherwise var1 is assigned true if var2 is var1 = var2 < var3 less than the value of var3, false otherwise var1 is assigned true if var2 is var1 = var2 > var3 greater than the value of var3, false otherwise var1 is assigned true if var2 is var1 = var2 = var3 greater than or equal to the value of var3, false otherwise

Figure 1 - Comparison Operators The program below demonstrates the functionality of comparison operators. using System; 1 namespace ComparisonOperators 2 { 3 class Program 4 { 5 static void Main() 6 { 7 int num1 = 10; 8 int num2 = 5; 9 10 Console.WriteLine("{0} 11num2); 12 Console.WriteLine("{0} 13num2); 14 Console.WriteLine("{0} 15 Console.WriteLine("{0} 16 Console.WriteLine("{0} 17num2); 18 Console.WriteLine("{0} 19num2); 20 } } }

== {1} : {2}", num1, num2, num1 == != {1} : {2}", num1, num2, num1 != < {1} : {2}", num1, num2, num1 < num2); > {1} : {2}", num1, num2, num1 > num2); =

Example 1

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

10 10 10 10 10 10

== != < > =

5 5 5 5 5 5

: : : : : :

False True False True False True

We first create two variables that will be compared. We initialize them with values. Then, we used each comparison operators to compare the two variables and prints the result. It is important to note that when doing comparisons, you must use the == operator instead of the = operator. The = operator is the assignment operator and an expression such as x = y is read as assign the value of y to x. The == operator is the equality operator which tests for equality of two values so an expression such as x == y is read as x is equal to y.

Logical Operators Logical operators typically involves boolean values and yields boolean results. There are often use to create multiple or complex conditions. We have learned that a boolean value can either be true or false. We can use the different logical operators available in C#. Suppose that var2 and var3 are boolean values. Operator Name Category Example && Logical AND Binary var1 = var2 && var3; || Logical OR Binary var1 = var2 || var3; ! Logical NOT Unary var1 = !var1; Figure 1 - Logical Operators

Logical AND Operator (&&) An expression using the logical AND operator evaluates to true if both operands are true. If either or both of the operands are false, the expression evaluates to false. The following shows the truth table for the logical AND operator. X Y X && Y true true true true false false false true false false false false Figure 2 - Logical AND && Truth Table

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

To better understand the effect of logical AND, remember that it can only yield true if both operands are true. All other combinations yields false. When using logical AND operator, the moment that the program sees that the first operand is false, then the result is automatically false. You can use the logical AND operator on boolean expressions such as those using comparison operators. For example, the following expression assigns true to the result if age is greater than 18 and salary is less than 1000. result = (age > 18) && (salary < 1000);

The logical AND operator is also useful when specifying range of values. For example, the mathematical notation 10 = 18);

We will later see a more practical use of the ! operator in a later lesson.

Bitwise and Bitshift Operators The bitwise operators allow you to manipulate different kinds of data in their binary form. In order to follow this lesson, it is recommended that you know what binary system is and how to convert decimal numbers to binary. Binary system is what the computer actually uses since it represents everything in on or off state. On is represented by 1 and off is represented by 0. Therefore, binary numbers can only be 1's or 0's. Binary numbers are also called Base 2 numbers and decimal numbers are Base 10. A bit represents one binary digit. A byte represents 8 bits. The int for example, uses 32 bit or 4 bytes to store its content. It means, it represents the numbers using 32 digits of 0's and 1's. For example, the number 100 when stored in an int variable is read by the computer as this: 000000000000000000000000000001100100

The decimal number 100 is equivalent to 1100100 in binary. But since it is only 7 digits, we added 29 more digits to the left of it to fill the 32 bits required by int. Note that we read binary numbers from right to left so the beginning digit is actually the last one. We can then use the bitwise operators to the binary versions of the numbers or data. You don't have to convert them to binary as the computer automatically sees them as binary numbers. The following shows the bitwise operators you can use. Operator Name Category Example & Bitwise AND Binary x = y & z; | Bitwise OR Binary x = y | z; ^ Bitwise XOR Binary x = y ^ z; ~ Bitwise NOT Unary x = ~y; &= Bitwise AND Assignment Binary x &= y; | Bitwise OR Assignment Binary x |= y;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Operator Name Category Example ^= Bitwise XOR Assignment Binary x ^= y; Figure 1 - Bitwise Operators Bitwise operators are commonly used in bitwise comparisons of Flags enumerations which you will learn in several advance lessons in this site.

Bitwise AND (&) Operator The bitwise AND operator does the AND operation to every bit of the binary representation of a value. When doing an AND operation (or ANDing) on two binary numbers, the result is 1 if both binary numbers are 1, and 0 otherwise. The AND operation has the following truth table. X Y X AND Y 1 1 1 1 0 0 0 1 0 0 0 0 Figure 2 - AND Truth Table As a demonstration of using the bitwise AND operator, let's take a look at the following code snippet. int result = 5 & 3; Console.WriteLine(result); 1

We used the bitwise AND to the values 5 and 3 and as you can see, it yields the value 1. Let's take a look at how the computer came up with that result. 5: 00000000000000000000000000000101 3: 00000000000000000000000000000011 -----------------------------------1: 00000000000000000000000000000001

We first covert 5 and 3 to their binary equivalents. SInce int has 32-bits, we added leading 0's to fill the 32 slots. We then use the AND operation to each digit. By looking at the truth table in Figure 2, we came up with the binary representation of the number 1. The assignment version of the bitwise AND operator is also available. myNumber &= 5;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The above statement applies the bitwise AND operator to whatever the value of myNumber and to the value of the right opearand (in this case 5). The result is then assigned to myNumber.

Bitwise OR (|) Operator The bitwise OR operator uses the OR operation on every bit of the binary representation of two values. The result of an OR operation is shown in the following truth table. X Y X OR Y 1 1 1 1 0 1 0 1 1 0 0 0 Figure 3 - OR Truth Table The OR operation yields 0 only if both operands are 0. If at least one value is 1, then it automatically yields 1. Let's take a look at an example of using this operator. int result = 7 | 9; Console.WriteLine(result); 15

In binary representation, you can see how the computer yields 15 when we used the bitwise OR operator on the two values. 7: 00000000000000000000000000000111 9: 00000000000000000000000000001001 ----------------------------------15: 00000000000000000000000000001111

We looked at the truth table in Figure 3 to determine the results of doing the OR operation on each digit of their binary representations. We came up with binary number 1111 which is equivalent to 15. The assignment version of the bitwise OR operator is also available. myNumber |= 5;

The above statement applies the bitwise OR operator to whatever the value of myNumber and to the value of the right operand (in this case 5). The result is then assigned to myNumber.

Bitwise XOR (^) Operator

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Bitwise XOR (Exculsive OR) performs XOR operations to each digit of the binary representation of two values. The following is the truth table for the XOR operation. X Y X XOR Y 1 1 0 1 0 1 0 1 1 0 0 0 Figure 4 - XOR Truth Table The XOR operation yields 0 if both operands are the same, that is, if both are 0's or both are 1's. Otherwise, it yields 1. The following example shows the effect of using the bitwise XOR operator on two values. int result = 5 ^ 7; Console.WriteLine(result); 2

The following shows their binary representations and how we arrived at the result value using the bitwise XOR operator. 5: 00000000000000000000000000000101 7: 00000000000000000000000000000111 ----------------------------------2: 00000000000000000000000000000010

By looking at the XOR truth table and applying the XOR operation on each binary digit pairs, we arrived at the final value which is the binary representation of 2. The assignment version of the bitwise XOR operator is also available. myNumber ^= 5;

The above statement applies the bitwise XOR operator to whatever the value of myNumber and to the value of the right operand (in this case 5). The result is then assigned to myNumber.

Bitwise NOT (~) Operator The bitwise NOT operator performs the NOT operation (inversion) to each binary digit of a number. It is a unary operator so it only needs one operand. The following is the truth table for the NOT operation. X NOT X 1 0

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

X NOT X 0 1 Figure 5 - NOT Truth Table The NOT operation simply inverts the value of a binary digit. The following shows an example of using the not operator. int result = ~7; Console.WriteLine(result);

Let's look at their binary representations. 7: 00000000000000000000000000000111 ------------------------------------8: 11111111111111111111111111111000

Inverting every binary digit of 7 results on the binary representation of -8. Binary representations of negative numbers are quite tricky. You need to use the Two's Compliment Notation to the binary form of -8 to see why the computer reads it as -8 (instead of a very big number).

Bitwise Operators Example Usage To show a practical example of using the bitwise operators, suppose you want to specify a certain style of a font. First, we can give specific numeric codes for each font style. Style Code Regular 0 Bold 1 Italic 2 Underline 4 Strikeout 8 Let's say the initial value of the fontStyle is 0 which means, the current font style uses regular (or no style). int fontStyle = 0;

To add the Bold font style, we can use the bitwise OR operator. Note that Bold is represented by code 1. fontStyle = fontStyle | 1;

To add the Italic font style to the current fontStyle, again, use the bitwise OR operator.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

fontStyle |= 2;

Since the fontStyle previously has the value 1 which means bold, adding the italic style 2 will perform bitwise OR operation on 1 and 2 resulting to 3. By looking at the table of styles above, there is no corresponding style for code 3. Therefore, we can assign the 3 to the new style BoldItalic which is a combination of Bold and Italic styles. If we are to add the Underline font style (8) to the current font style (3), the result will be 11, which can represent the font style which is Bold, Italicized, and Underlined at the same time. Say you want to assign a new style which is a combination of all the styles, then you can simply use the bitwise OR operator between each font style. fontStyle = 1 | 2 | 4 | 8;

To test if a style is part of the overall font style, we can use the bitwise AND operator. bool isBold = (fontStyle & 1) == 1;

The expression tests if ANDing the current fontStyle yields to the style being tested. If so, the result of the expression is true, otherwise false. If you want for example to remove the Underline style to the current font style, you can use the XOR operator. fontStyle = fontStyle ^ 8; //or fontStyle ^= 8;

Once the Underline style is removed, using the bitwise XOR operator again will add the Underline style instead of removing it. The previous example represented the font styles using plain integers which is hard to read. The proper way is by using enumerations which we will be discussing in an upcoming lesson.

The Bitwise Shift Operators Another pair of operators, called the bitwise shift operators allows you to shift the position of the bits to the left or to the right. Both operators accept two operands, the left being the value whose binary representation will be shifted, and the right operand specifies the number of positions to shift to left or right. Operator >

Name Left Shift Operator Right Shift Operator

COMPILED BY:

Category Example Binary Binary

x = y > 2;

Bsc ABDULRAHIM ALI ATHUMAN

Operator =

Name

Category Example

Left Shift Assignment Binary Right Shift Assignment Binary

x = 2;

Figure 6 - Bitwise Shift Operators The Left Shift Operator ( 10) 22 Console.WriteLine("Goodbye World."); 23 } 24 } 25}

Example 1 - Using the if Statement   



  

Hello World. Goodbye World.

Line 10 declares a variable named number with a value of 5. When we reach the first if statement in line 13, the program determines if the number is less than 10, that is if 5 is less than 10. Logically, it results to true so the if statement's corresponding statement to execute (line 14) will be executed resulting to printing the message "Hello World.". After that, we change the value of number to 15 (line 18). When it reach the second if statement in line 21, it sees that 15 is indeed greater than 10 and executes the message "Goodbye World." in line 22. Note that it doesn't matter if you write the if statement in one line as in: if ( number > 10 ) Console.WriteLine("Goodbye World.");

As long as you have a single statement to execute and you terminate the statement with a semicolon, the above code is valid.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN



You can have multiple statements inside an if statement. You need to put curly braces to mark the start and end of the set of statements to execute. Everything inside the curly braces is considered the block or body of the if statement. Not placing curly braces will lead to your program not doing what you expected. The following is the syntax of an if statement with multiple statements in its block.

               

if (condition) { statement1; statement2; . . . statementN; }

  

if (x > 10) Console.WriteLine("x is greater than 10."); Console.WriteLine("This is still part of the if statement. (Really?)");

    

The above code is better read if we put the proper indentions for the statements.

Let's look an an example with this code snippet: if (x > 10) { Console.WriteLine("x is greater than 10."); Console.WriteLine("This is still part of the if statement."); }

The code above will output the two messages if the value of x is greater than 10. If for instance, we remove the curly braces and the value of x is not greater than 10 such as the following code snipppet:

if (x > 10) Console.WriteLine("x is greater than 10."); Console.WriteLine("This is still part of the if statement. (Really?)");

You can see that the second statement is actually not part of the if statement. The code will only print the second line because the value of x is less than 10 and the condition for the if statement will result to false. That's why curly braces are important. As a good practice, always write curly braces even if you only have one statement in the body of the if statement so whenever you want to add another statment inside it, you won't forget adding curly braces which will result to errors which are hard to find. One common mistake of new programmers is putting a semicolon right after the right parenthesis of the if statement's condition. Consider the following example.  

if (x > 10); Console.WriteLine("x is greater than 10");

This will lead to the if statement having no statements to execute. The second will be not part of the if statement. Although this would compile, your program will yield logic errors. So always COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

remember to not put a semicolon at the end of the condition of an if statement because doing so will signify that the if statement's code block has ended there. 

Let's take a look at another example of using if statements.

1 using System; 2 3 namespace IfStatementDemo2 4 { 5 public class Program 6 { 7 public static void Main() 8 { 9 int firstNumber; 10 int secondNumber; 11 12 Console.Write("Enter a number: "); 13 firstNumber = Convert.ToInt32(Console.ReadLine()); 14 15 Console.Write("Enter another number: "); 16 secondNumber = Convert.ToInt32(Console.ReadLine()); 17 18 if (firstNumber == secondNumber) 19 { 20 Console.WriteLine("{0} == {1}", firstNumber, secondNumber); 21 } 22 if (firstNumber != secondNumber) 23 { 24 Console.WriteLine("{0} != {1}", firstNumber, secondNumber); 25 } 26 if (firstNumber < secondNumber) 27 { 28 Console.WriteLine("{0} < {1}", firstNumber, secondNumber); 29 } 30 if (firstNumber > secondNumber) 31 { 32 Console.WriteLine("{0} > {1}", firstNumber, secondNumber); 33 } 34 if (firstNumber = secondNumber) 39 { 40 Console.WriteLine("{0} >= {1}", firstNumber, secondNumber); 41 } 42 } 43 } 44}

Example 2  

Enter a number: 2 Enter another number: 5

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

             



      

2 != 5 2 < 5 2 3 10 >= 3 Enter a number: 5 Enter another number: 5 5 == 5 5 = 5

We used the comparison operators as condition for each if statements. We asked an input from the user for two numbers that will be involved on the comparisons. The numbers will be compared inside every if statements and print the corresponding message if the condition results to true. Note that conditions are boolean values which are results of a comparison expression. Therefore, you can store the result of an expression in a boolean variable and then use the variable as the condition in an if statement. bool isNewMillenium = year == 2000; if (isNewMillenium) { Console.WriteLine("Happy New Millenium!"); }

If the value of year is indeed 2000, then the expression will yield true and be stored in variable isNewMillenium. We can use the variable to determine if the if statement's body will execute depending on whether the value of the variable is true or false.

The if else Statement 

The if statement we presented last time is only good if you want to execute a code when one condition is met. But what would you do if you want execute another set of codes when that condition is not met? The if else statement serves this purpose because it is a double-selection conditional statement. It means, you can specify another behavior when the specified condition is false. Below is the syntax of an if else statement.

        

if (condition) { code to execute if condition is true; } else { code to execute if condition is false; }

The else keyword can't be use by itself. It must have a matching if statement. The curly braces are optional if you only have one statement to execute for each of the body of if

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

and else. The code inside the else block will only be executed if the condition inside the if statment results to false. I'll show you an example of using the if else statement. using System; 1 2 namespace IfElseStatementDemo 3 { 4 public class Program 5 { 6 public static void Main() 7 { 8 int number = 5; 9 10 //Test the condition 11 if (number < 10) 12 { 13 Console.WriteLine("The 14 } 15 else 16 { 17 Console.WriteLine("The 18equal to 10."); 19 } 20 21 //Modify value of number 22 number = 15; 23 24 //Repeat the test to yield 25 if (number < 10) 26 { 27 Console.WriteLine("The 28 } 29 else 30 { 31 Console.WriteLine("The 32equal to 10."); 33 } 34 } 35 } }

number is less than 10.");

number is either greater than or

a different result number is less than 10.");

number is either greater than or

Example 1 - Using the if else Statement   

The number is less than 10. The number is either greater than or equal to 10.

The output shows the functionality of the if else statement. When the value of number is less than 10, it met the condition and executes the code that is inside the if block. When the value of number was modified to have a value which is greater than 10, the condition resulted to false and the code block of else was executed. Do not use the else block if it has no corresponding if block. Like the if statement, do not add a semicolon immediately after the else keyword.

Conditional Operator COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN



The conditional operator (?:) in C# does the same thing as the if else statement though it is more suited on simple statements such as assigning two different values depending on a specified condition. Below shows the syntax of using this operator.

 

? :

The conditional operator is C#'s only ternary operator as it requires three operand, the condition, the value when the condition is true, and the value when the condition is false. Let's take a look at how to use this operator inside a program.

1 namespace ConditionalOperatorDemo 2 { 3 public class Program 4 { 5 public static void Main() 6 { 7 string pet1 = "puppy"; 8 string pet2 = "kitten"; 9 string type1; 10 string type2; 11 12 type1 = (pet1 == "puppy") ? "dog" : "cat"; 13 type2 = (pet2 == "kitten") ? "cat" : "dog"; 14 } 15 } 16}

Example 1 - Using the Conditional Operator 

     

The above program demonstrates the use of the conditional operator. The first line translates like this; if the value of pet1 is "puppy" then assign "dog" to type1, otherwise, assign "cat" to type1. Same goes with the second line; if the value of pet2 is "kitten" then assign "cat" to type2, "dog" otherwise. Let's transform the following line of code to it's equivalent if else statement to make it even clearer. If we rewrite this using if else statement, it will look like this. if (pet1 == "puppy") type1 = "dog"; else type1 = "cat";

Avoid using the conditional operator when you have multiple statements inside an if or else block. Sometimes, the conditional operator can make code less readable.

Multiple Selection if Statements What if you have more conditions to test? You can write multiple if statements but woudn't it be better if you can combine those if statements into one whole list. You can have multiple selection in an if statement using the syntax below.   

if (condition) { code to execute;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

                   

} else { if (condition) { code to execute; } else { if (condition) { code to execute; } else { code to execute; } } }

               

if (condition) { code to execute; } else if (condition) { code to execute; } else if (condition) { code to execute; } else { code to execute; }

The code above is hard to read. You are branching if statements inside the else blocks. There's a better way of doing this. We could rewrite the code above and make it simpler.

We introduce using the else if statement. Like the else, the else if must have a corresponding if statement. The else if statement executes if the first if statement is not true. The condition of the else if is then tested and if false, the other else if statements will be executed. If no other else if is found, the else block will be executed instead. Lets make a program that will demonstrate the else if statements. 1 using System; 2 3 namespace MultipleSelectionIfStatementsDemo 4 { 5 public class Program

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48}

{ public static void Main() { int choice; Console.WriteLine("What's your favorite color?"); Console.WriteLine("[1] Black"); Console.WriteLine("[2] White"); Console.WriteLine("[3] Blue"); Console.WriteLine("[4] Red"); Console.WriteLine("[5] Yellow\n"); Console.Write("Enter your choice: "); choice = Convert.ToInt32(Console.ReadLine()); if (choice == 1) { Console.WriteLine("You might like my black t-shirt."); } else if (choice == 2) { Console.WriteLine("You might be a clean and tidy person."); } else if (choice == 3) { Console.WriteLine("You might be sad today."); } else if (choice == 4) { Console.WriteLine("You might be inlove right now."); } else if (choice == 5) { Console.WriteLine("Lemon might be your favorite fruit."); } else { Console.WriteLine("Sorry, your favorite color is " + "not in the choices above."); } } }

Example 1 - Using Multiple Selection if Statements         

What's your favorite color? [1] Black [2] White [3] Blue [4] Red [5] Yellow Enter your choice: 1 You might like my black t-shirt.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

        

What's your favorite color? [1] Black [2] White [3] Blue [4] Red [5] Yellow Enter your choice: 999 Sorry, your favorite color is not in the choices above.

The output will vary depending on what choice you give to the program. Depending on what you choose, the program will print a different message. Take note about the else statement. If the number you typed is not in the choices, then the code inside the else block will be executed.

Nesting if Statements You can nest if statements in C#. This is simply placing if statements inside if statements. You can make something as complex as the code that follows. if (condition) { code to execute; if (condition) { code to execute; } else if (condition) { if (condition) { code to execute; } } } else { if (condition) { code to execute; } }

Let's try a program that uses nested if statements. 1 using System; 2 3 namespace NestingIfStatementsDemo 4 { 5 public class Program 6 {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42}

public static void Main() { int age; string gender; Console.Write("Enter your age: "); age = Convert.ToInt32(Console.ReadLine()); Console.Write("Enter your gender (male/female): "); gender = Console.ReadLine(); if (age > 12) { if (age < 20) { if (gender == "male") { Console.WriteLine("You are a teenage boy."); } else { Console.WriteLine("You are a teenage girl."); } } else { Console.WriteLine("You are already an adult."); } } else { Console.WriteLine("You are still too young."); } } }

Example 1 - Nesting if Statements Enter your age: 18 Enter your gender: male You are a teenage boy. Enter your age: 12 Enter your gender: female You are still too young.

Let's disect the program. First, the program will ask you for your age (line 13). Line 16 asks for your gender. Then the program will hit the first if statement in line 18. It will test if you will past the first condition and that's if your age is greater than 12. If you pass this condition, you will move inside the body of the if statement. If not, you jump to the corresponding else block (line 34) of that if statement. Let's say you pass the first condition, and you are now inside the block of the first if statement. Inside it, you will meet a second nested if statement (line 20). It will determine if your age is less than 20. If you pass this, you will be taken into its code block, but if not, you will jump again to the it's else pair in line 31. Let's assume the value of your age is

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

indeed less than 20, then you will be taken inside its body and there you will encounter yet another if statement (line 22). This will look at your gender and if it is "male", then you will execute the code inside the body of the 3rd if statement, if not, it will execute the body of the else statement (line 26). The nesting ends there. If possible, avoid so much nesting of if statements. This makes your code very confusing to read. You can avoid using too many nested if statements using logical operators.

Using Logical Operators Logical operators allows you to combine multiple conditions. These operators involves at least two conditions and the final boolean result is determined by the operator being used. Let's take a look at some logical operators. Operator Pronounced as

&&

And

||

Or

!

Not

Example

Effect z will be assigned a value of true if both z = (x > 2) && (y < 10) the conditions are true. If one of the conditions results to false, then z will automatically assigned a value of false. z will be assigned a value of true if at least one of the z = (x > 2) || (y < 10) conditions is true. If there's no condition that results to true, then z will be assigned a value of false. z will be assigned a value of true if the condition z = !(x > 2) results to false, and false, if the condition results to true.

Figure 1 For example, you can read z = (x > 2) && (y < 10) as "Assign z with true if the value of x is greater than 2 AND the value of y is less 10, false otherwise". The sentence suggest that it requires to have all the conditions to be true in order for the statement to be true. You passed the subject if you passed the final exam AND you got a passing grade. This means you cannot pass the subject if you neither pass the final exam nor have a passing grade or both. The use of || (logical OR) is a different effect than the && (logical AND). The logical OR operator results to true if at least one of the conditions is true. If none of those conditions is true, then it will result to falsity. You can even combine both logical AND and logical OR in an expression like this: if ( (x == 1) && ( (y > 3) || z < 10) ) ) { //do something here }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The use of parentheses is important here. We use it to group the conditions. First, it will calculate the result of (y > 3) || (z < 10) because it is considered as a group thanks to the parentheses. The result will then be the right operand of the logical AND and will be compared to (x == 1) condition. The result will determine if the program should execute the code in its body. We wrote a program on our previous lesson. Lets make some modifications in it to show how to use a logical operator inside a program. 1 using System; 2 3 namespace LogicalOperatorsDemo 4 { 5 public class Program 6 { 7 public static void Main() 8 { 9 int age; 10 string gender; 11 12 Console.Write("Enter your age: "); 13 age = Convert.ToInt32(Console.ReadLine()); 14 15 Console.Write("Enter your gender (male/female): "); 16 gender = Console.ReadLine(); 17 18 if (age > 12 && age < 20) 19 { 20 if (gender == "male") 21 { 22 Console.WriteLine("You are a teenage boy."); 23 } 24 else 25 { 26 Console.WriteLine("You are a teenage girl."); 27 } 28 } 29 else 30 { 31 Console.WriteLine("You are not a teenager."); 32 } 33 } 34 } 35}

Example 1 - Logical Operators Enter your age: 18 Enter your gender (male/female): female You are a teenage girl. Enter you age: 10 Enter your gender (male/female): male You are not a teenager.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The modified program shows you the logical operator AND in action (line 16). When you reach the if statement, the program determines if your age is between 12 and 20. First, it checks if your age is greater than 12 then it checks if your age didn't exceed 20. If both of these are true, then it will execute the code inside the if block. If one condition yields false such as meeting the condition that you are older than 12 but not younger than 20, then it will execute the code inside the else block. The && operator evaluates the left operand. If it is false, then it skips evaluating the right operand and automatically yield false as the result. In contrast, the || operator evaluates the left operand and if it is true, then it skips the evaluation of the right operand and immediately yields true. One important thing to note is that you can also use the operators & and | which are the bitwise AND and OR operators. if (x == 2 & y == 3) { //Some code here } if (x == 2 | y == 3) { //Some code here }

One minor difference of this operators on the logical operators we have discussed is that they evaluate the two operands regardless of the value of the left operand. For example, even if the left operand is false, the right operand is still evaluated by the bitwise AND operator (&). If you are combining conditions, it would be better to use the logical AND (&&) and OR (||) operators instead of the bitwise AND (&) and OR (|) operators. There's another logical operator that I would like to show. The NOT Operator (!) is used to negate or inverse the effect of an expression.Consider the following example: if (!(x == 2)) { Console.WriteLine("x is not equal to 2."); }

If the expression x == 2 evaluates to false, the ! operator reverses the result from false to true.

The switch Statement C# offers switch statements which allows you to have multiple selections based on a constant value of a variable. A switch statement is equivallent to a multiple selection if statement but a switch statement is used if the variable to be compared has a constant value such as a number, a string, or a character. Constant values are values that doesn't change. Below shows the syntax of a switch statement.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

switch (testVar) { case compareVal1: code to execute break; case compareVa12: code to execute break; . . . case compareVa1N: code to execute break; default: code to execute break; }

if testVar == compareVa11; if testVar == compareVa12;

if testVer == compareVa1N; if none of the values above match the testVar;

You pass a variable to a switch statement. This variable is then compared to each case statement inside the block of the switch. If the variable matched a value in a case statement, the code of that particular case statement is executed. Note that even if the number of lines of code inside a case statement is more than one, we don't use curly braces. The end of the body of a case statement is determined by the keyword break which brings the program outside of the switch statment and executes any code following the structure. If this is omitted, then you will encounter an error. The switch statement also has a default statement which is executed if none of the values of all the case statements match the value of the test variable. The default statement is optional and nothing will happen if you remove it except that nothing will be executed if no values match the cases.The position of the default statement is not important but it is a habit to place it below. Let's look at an example of how to use a switch statement. 1 using System; 2 3 namespace SwitchStatementDemo 4 { 5 public class Program 6 { 7 public static void Main() 8 { 9 int choice; 10 11 Console.WriteLine("What's your favorite pet?"); 12 Console.WriteLine("[1] Dog"); 13 Console.WriteLine("[2] Cat"); 14 Console.WriteLine("[3] Rabbit"); 15 Console.WriteLine("[4] Turtle"); 16 Console.WriteLine("[5] Fish"); 17 Console.WriteLine("[6] Not in the choices"); 18 Console.Write("\nEnter your choice: "); 19

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41choices."); 42 43 44 45 46 47 } 48 } }

choice = Convert.ToInt32(Console.ReadLine()); switch (choice) { case 1: Console.WriteLine("Your break; case 2: Console.WriteLine("Your break; case 3: Console.WriteLine("Your break; case 4: Console.WriteLine("Your break; case 5: Console.WriteLine("Your break; case 6: Console.WriteLine("Your

favorite pet is Dog."); favorite pet is Cat."); favorite pet is Rabbit."); favorite pet is Turtle."); favorite pet is Fish."); favorite pet is not in the

break; default: Console.WriteLine("You don't have a favorite pet."); break; }

Example 1 - Using a switch Statement What's your favorite pet? [1] Dog [2] Cat [3] Rabbit [4] Turtle [5] Fish [6] Not in the choices Enter your choice: 2 Your favorite pet is Cat. What's your favorite pet? [1] Dog [2] Cat [3] Rabbit [4] Turtle [5] Fish [6] Not in the choices Enter your choice: 99 You don't have a favorite pet.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The program above lets you pick what your favorite pet is. Each pet has been assigned a corresponding number. You enter that number and then it was compared inside the switch structure. If a matching number in a case statement is found, the appropriate message is shown. If none of the case statements match, then the default statement is executed. Another feature of the switch statement is that you can make two or more case values to execute one set of codes. For example, what if you want values 1, 2, and 3 to execute one set of code? You simply write a case immediately after another. switch(number) { case 1: case 2: case 3: Console.WriteLine("This code is shared by three values."); break; }

I said earlier that a switch statment is equivalent to a multiple selection if statement. So another way to write the program in Figure 1 is like this: if (choice == 1) Console.WriteLine("Your favorite pet is Dog."); else if (choice == 2) Console.WriteLine("Your favorite pet is Cat."); else if (choice == 3) Console.WriteLine("Your favorite pet is Rabbit."); else if (choice == 4) Console.WriteLine("Your favorite pet is Turtle."); else if (choice == 5) Console.WriteLine("Your favorite pet is Fish."); else if (choice == 6) Console.WriteLine("Your favorite pet is not in the choices."); else Console.WriteLine("You don't have a favorite pet.");

The code above will have exactly the same result as the switch statment. Notice that the default statement is equivalent to the else statement. So what should you use between the two? We use switch statement if the value to be compared is constant or is not changing. So the below code is prohibited. int myNumber = 5; int x = 5; switch (myNumber) { case x: Console.WriteLine("Error, you can't use variables as a value" + " to be compared in a case statment."); break; }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can see here that even though x has a value of 5 which obviously matches the value of the test variable myNumber, an error occured because x is not constant, or to say it in other words, it has a possibility of changing its value. If you want to use x and yield no error, you have to make it a constant variable. int myNumber = 5; const int x = 5; switch (myNumber) { case x: Console.WriteLine("Error has been fixed!"); break; }

We used the const keyword to make the value constant. Note that after declaring a variable as constant, you won't be able to change its value anywhere in a program. Also note that you need to supply a value in the declaration of a constant variable. A switch statement must match a value of the test variable to the case value so you cannot test if a test variable is less than or greater than the other value. For example, there is no such thing as this: switch (myNumber) { case x > myNumber: Console.WriteLine("switch staments can't test if a value is less than " + "or greater than the other value."); break; }

Therefore, it is harder to test if the test value is equal to a range of values. This time, you have to use the multiple selection if statement because you will have hard time if you stick with switch statements.

Looping Looping allows you to repeat a set of code or statements while a given condition is true. Without it, you have to write multiple similar codes just to make your program repeat and that is tedious. Suppose you want to print "Hello World." 10 times. It will look like this without using a loop. Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello Console.WriteLine("Hello

COMPILED BY:

World."); World."); World."); World."); World."); World."); World."); World."); World."); World.");

Bsc ABDULRAHIM ALI ATHUMAN

Of course you can copy the first line and just hit Ctrl + V to paste the other nine, but what I'm trying to show you here is inefficiency. There is a way to better write all of these lines of code and that's by using a loop. There are different kinds of looping structure in C#.   

while Loop do while Loop for Loop

The while Loop The while loop is the most basic looping structure in C#. It takes one condition and a set of codes that it will execute for as long as the condition remains true. The basic syntax of a while loop is as follows.    

while(condition) { code to loop; }

As you can see, the syntax is as simple as the structure of an if statement. We first write the condition which is a boolean statement and if that condition is true, then it will execute the code. If the condition is not true when the program reaches the while loop, then it will not execute the code at all. For a looping to stop, there must be some kind of modification to the values inside the while loop. You will be needing a counter variable that will be used inside the body of the while loop. This counter will be used in the condition to test if the loop should continue. Then inside the body, you must increment or decrement it. Lets look at an example program that will show you how to use a while loop. 1 using System; 2 3 namespace WhileLoopDemo 4 { 5 public class Program 6 { 7 public static void Main() 8 { 9 int counter = 1; 10 11 while (counter 0); 10 15 20

The Contains method can also be used to check if the string exists in another string. string str1 = "This is a sample string."; Console.WriteLine(str1); if (str1.Contains("sample")) { Console.WriteLine("\"sample\" exists in the string."); } This is a sample string. "sample" exist in the string.

The Contains method returns true if the search string does exist, and false if it does not. Another pair of methods, StartsWith() and EndsWith() are used to find if a string begins or ends with a particular string. string str1 = "Apple"; Console.WriteLine(str1); if (str1.StartsWith("A")) { Console.WriteLine("The word starts with A."); } if (str1.EndsWith("e")) { Console.WriteLine("The word ends with e."); } Apple The word starts with A. The word ends with e.

Extracting, Removing and Replacing Strings If you want to extract a part of a string, you can use the Substring() method. The Substring() method accepts two arguments, the start index and the length of the string to extract. The following program shows you this. string str1 = "This is a sample string."; //Extract sample

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

string str2 = str1.Substring(10, 6); Console.WriteLine("str1 = {0}", str1); Console.WriteLine("str2 = {0}", str2); str1 = This is a sample string. str2 = sample

We started the extraction at index 10. You can see that "sample" starts at index 10 (11th character). The length will determine how many characters will be extracted. Since we provided six as the length, 6 characters was extracted including the character at the start index. If you don't want to count manually the position of the "sample", you can use the IndexOf method. string str2 = str1.Substring(str1.IndexOf("sample"), 6);

Another overload of the Substirng method accepts only one argument which is the start index. It starts the extraction from the start index until the end of the string.

Removing Strings To remove strings, you can use the Remove method. It's parameters are the same as the Substring method. string str1 = "This is a sample string."; Console.WriteLine(str1); Console.WriteLine("Removing \"sample\"..."); str1 = str1.Remove(10, 7); Console.WriteLine(str1); This is a sample string. Removing "sample "... This is a string.

Another overload of the Remove method accepts one argument which is the start index. Everything will be removed from the start index to the end of the string.

Replacing Strings You can use the Replace method to replace all occurrences of a string with another string. For example, you can change all occurrences of "dog" with "cat". string str1 = "That dog is a lovely dog."; Console.WriteLine(str1); Console.WriteLine("Replacing all dogs with cats..."); str1 = str1.Replace("dog", "cat"); Console.WriteLine(str1); That dog is a lovely dog. Replacing all dogs with cats... That cat is a lovely cat.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Replace method accepts two arguments. The first one is the string to be replaced and the second one is the replacement string. The Replace method searches for all occurences of the word "dog" then replaced it with the word "cat". You can also use the Replace method to remove all occurances of a string. string str1 = "That dog is a lovely dog."; Console.WriteLine(str1); Console.WriteLine("Removing all dogs..."); str1 = str1.Replace("dog", String.Empty); Console.WriteLine(str1); That dog is a lovely dog. Removing the dogs... That is a lovely .

The code above uses String.Empty as the replacement string. String.Empty is equal to "" which means empty string. So every occurances of the string being replace was emptied thus removing them from the actual string.

Changing the Casing of Strings You can change the casing of a string. For example, a string composing of lowercase letters can be transformed into all caps. We use the ToUpper() and ToLower() instance methods which returns an uppercase or lowercase version of the string. string lowercase = "abc"; string uppercase = "ABC"; Console.WriteLine("lowercase.ToUpper() = " + lowercase.ToUpper()); Console.WriteLine("uppercase.ToLower() = " + uppercase.ToLower()); lowercase.ToUpper() = ABC uppercase.ToLower() = abc

Note that if a string has different cases, such as a sentence where the first character is in uppercase and the rest is in lowercase, then using ToUpper() only changes the case of the characters in lowercase and does not affect the ones which are already in uppercase. Same goes with the ToLower() method. Let's apply what we have learned by creating a function that converts a sentence into Title Case, that is, every word starts with a capital letter. The following program uses some of the string manipulation methods we have learned so far. class Program { static string ToTitleCase(string str) { string[] words = str.Split(' '); for(int i = 0; i < words.Length; i++) {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

string firstLetter = words[i].Substring(0, 1); string rest = words[i].Substring(1); string result = firstLetter.ToUpper() + rest.ToLower(); words[i] = result; } return String.Join(" ", words); } static void Main() { string input; Console.WriteLine("Enter a string: "); input = Console.ReadLine(); Console.WriteLine("Converting to Title Case..."); input = ToTitleCase(input); Console.WriteLine(input); } } Enter a string: tHe quICK bROwN fOx Converting to Title Case... The Quick Brown Fox

We created a function named ToTitleCase which accepts one string argument which is the string that will be modified. string[] words = str.Split(' ');

We first split the strings into multiple words so we can manipulate each word. We then enter a for loop to loop through all the words. string firstLetter = words[i].Substring(0, 1); string rest = words[i].Substring(1);

We then extract the first letter of the word and put it in a variable for later use. We also extract the rest of the letters of the word. string result = firstLetter.ToUpper() + rest.ToLower();

We combine the extracted strings but we used the ToUpper for the first letter and ToLower for the rest of the word. After that, we replaced the content of the current element of the array with the modified word. return String.Join(" ", words);

Now, we combine the modified words and put spaces between the words. We then return it to the caller.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

String Formatting .NET provides you with ways to format the output of strings. You can use the String.Format to format your strings using different format specifiers. string str1 = "This"; string str2 = "That"; string str3 = String.Format("{0} and {1}", "This", "That"); Console.WriteLine(str3); This and That

The String.Format method accepts the string containing the format specifiers ({0},{1} and so on), and the following arguments are the strings that will be formatted by those format specifiers. The compier looks at the numbers in the format specifier, takes the argument with the same index in the argument list, and makes the substitution. The format specifiers automatically converts the data into string. Right now, there is no formatting that took place. We will save that for later. You might notice that String.Format is quite like the Console.WriteLine method. In fact, Console.WriteLine uses the same technique described above. Since { and } indicates the start and end of a format specifier, what if you want to print these characters? Console.WriteLine("{{{0}}}", 7); {7}

To print a { or }, you simply put two of each. In the code above, between the pairs of those braces lies the format specifier {0} that's why it was replaced by 7 in the output. It is important to understand that the argument associated with a format specifier is determined by the argument number, not the argument's position in the argument list. This means the same argument can be output more than once within the same call to WriteLine(). It also means that arguments can be displayed in a sequence differently than they are specified in the argument list. For example, consider the following program: Console.WriteLine("{0} {0} {0} {1} {1}", "hello", "world"); hello hello hello world world

Numeric Format Specifiers You can use a list of numeric format specifiers to format numbers to format numerical data: Console.WriteLine("{0:C}", 500); $500.00

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can see that the integer 500 was formatted into a currency using the C: and then the numeric format specifier af the for specifier index ("{0:C}";). You can also use precision specifiers which are numbers that modify the result of the formatting. For example, if you want 3 decimal places for a number, you do the following: Console.WriteLine("{0:F3}", 100); // 500.000

A list of numeric format specifiers is listed below. Specifier

Format

Meaning of Precision Specifier Specifies the number of decimal places.

C

Currency

c

Same as C

D

Whole number numeric data. (Use with integers only.)

d

Same as D.

E

Scientific notation (uses uppercase E)

e

Scientific notation (uses lowercase e)

F

Fixed point notation.

f G g

Same as F. Use either E or F format, whichever is shorter. Use either e or f format, whichever is shorter.

N

Fixed-point notation, with comma seperators.

n

Same as N.

P

Percentage

Specifies the number of decimal places.

p

Same as P. Numeric value that can be parsed, using Parse(), back into its equivalent internal form. (This is called the "round-trip" format.) Same as R.

Not used.

R r X

x

Minimum number of digits. Leading zeros will be used to pad the result, if necessary. Specifies the number of decimal places. The deafult is six. Same as E Specifies the number of decimal places. See E and F. See e and f. Specifies the number of decimal places.

Minimum number of digits. Hexadecimal (uses uppercase letters A through F) Leading zeros will be used to pad the result, if necessary. Minimum number of digits. Hexadecimal (uses lowercase letters a through f) Leading zeros will be used to pad the result, if necessary.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The precise effect of certain format specifiers depends upon the cultural settings. For example, the currency specifier, C, automatically displays a value in the monetary format of the selected culture. For most users, the default cultural information matches their locale and language. Thus, the same format specifier can be used without concern about the cultural context in which the program is executed. Here is a program that demonstrates several of the numeric format specifiers: double v = 17688.65849; double v2 = 0.15; int x = 21; Console.WriteLine("{0:F2}", v); // 17688.66 Console.WriteLine("{0:N5}", v); // 17, 688.65849 Console.WriteLine("{0:e}", v); // 1.768866e+004 Console.WriteLine("{0:r}", v); // 17688.65849 Console.WriteLine("{0:p}", v2); // 15.00 % Console.WriteLine("{0:X}", x); // 15 Console.WriteLine("{0:D12}", x); // 000000000021 Console.WriteLine("{0:C}", 189.99); // $189.99

Notice the effect of the precision specifier in several of the formats. Also note that you can use the ToString() method and pass the numeric format specifier. int x = 500; Console.WriteLine(x.ToString("C")); // $500.00

Padding with Format Specifiers You can also used the format specifiers to add padding to the string. The following demonstrates just that: Console.WriteLine("{0,10}", "hello"); Console.WriteLine("{0,-10}{1}", "hello", "world"); hello hello world

You use the following syntax {x:y} where x is the argument number, and y is the length of the padding. A positive length adds the padding to the left while a negative length adds the padding to the right. The amount of padding is determined by the length of the string which will be substituted. For example, if the length of the string is 5 and the length of the padding is 10, then the actual padding that will be displayed is 5 spaces. If the length of the padding is less that the length of the string, then nothing will happen. You can even combine them with numeric format specifiers such as the following: Console.WriteLine("{0,10:C}", 500); $500.00

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Note that the padding depends on the length of the formatted so even though 500 has a length of 3 and the final padding is supposed to be 7, the padding was reduced to 4 because of the $ sign the decimal point the the two zeroes that has been added by the numeric format specifier.

Custom Numeric Format Custom numeric format specifiers allows you to indicate an example of how you will represent your output. You will be using different special characters which function as placeholders. The following table presents the available custom format placeholder characters. Placeholder Meaning # Digit . Decimal point , Thousands seperator % Percentage, which is the value being formatted multiplied by 100. 0 Pads with leading and trailing zeros ; Seperates sections that describe the format for positive, negative, and zero value. E0 E+0 E-0 Scientific notation. e0 e+0 e-0 The period specifies the position of the decimal point. The # placeholder can hold a digit and can occur on the left or right side of the decimal point, or even by itself. If the # appears in the right side of the decimal point, it specifies the precission of the number of decimal digits. The value will be rounded if it is neccessary. If the # is found in the left of the decimal point, it specifies the digit positions for the whole-number part of the value and leading zeroes will be added if deemed neccessary. If the actual number has more digits the the number of #'s to the left of the decimal point, all the digits will be displayed. For example, if the number is 12345 and you only use ### which can only hold 3 digits, then all the five digits will still be displayed. If the original value has a decimal part and you use no decimal portion in your custom numeric format specifier, the value will be rounded to a whole number. For example, if the original value is 123.45 and you used ###, then it will be rounded down to 123. Zeroes are not siginificant such as a trailing zero, therefore, they will not be displayed. This causes a somewhat odd effect because a format such as ##.## displays nothing at all if the value being formatted is 0. To display a zero, you use the 0 placeholder instead as seen in the table above. You use the 0 placeholder to add leading or trailing zeroes. It can be placed on both left or right of the decimal point. Console.WriteLine("{0:00##.#00}", 21.3); // 0021.300

You can place commas into large numbers to indicate the thousands position. For example: Console.WriteLine("{0:#,###.#}", 3421.3); // 3,421.3

You don't need to specify a comma for each position. Commas will automatically inserted for every third digit from the left of the decimal point. For example:

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Console.WriteLine("{0:#,###.#}", 8763421.3); // 8,763,421.3

Commas have another meaning. When they occur on the immediate left of the decimal point, they act as a scaling factor. Each comma causes the value to be divided by 1,000. For example: Console.WriteLine("{0:#,###,.#}", 8763421.3); // 8,763.4

As the output shows, the value is scaled in terms of thousands. In addition to the placed holders, a custom format specifier can contain other characters. Any other characters are simply passed through, appearing in the formatted string exactly as they appear in the format specifier. For example, this WriteLine() statement: Console.WriteLine("Fuel efficiency is {0:##.# mpg}", 21.3); // 21.3 mpg

You can also use the escape sequences, such as \t or \n, if necessary. The E and e placeholders cause a value to be displayed in scientific notation. At least one 0, but possibly more, must follow E or e. The 0's indicate the number of decimal digits that will be displayed. The decimal component will be rounded to fit the format. Using an uppercase E causes an uppercase E to be displayed; using a lowercase e causes a lowercase e to be displayed. To ensure that a sign character precedes the exponent, use the E+ or e+ forms. To display a sign character for negative values only, use E,e,E-,e-. The ";" is a seperator which enables you to indicate different formats for positive, negative, and zero values. Here is the general form of a custom specifier that uses the ";": positivefmt;negative-fmt;zero-fmt. For example: Console.WriteLine("{0:#.##;(#.##);0.00}", num);

If num is positive, the value that will be displayed has two decimal places otherwise, if it is negative, the value is displayed with two decimal places and is inside a set of perentheses. If num is zero, 0.00 will be displayed. When you use seperators, there is no need to supply all parts. If you just want to specify how positive and negative values will look, omit the zero format. To use the default for negative values, omit the negative format. In this case, the positive format and the zero format will be seperated by two semicolons. The following example demonstrates just a few of the many possible custom formats that you can create: double num = 64354.2345; Console.WriteLine("{0:#.##}", num); // 64354.23 Console.WriteLine("{0:#,###.##}", num); // 64,354.23 Console.WriteLine("{0:#.###e+00}", num); // 6.435e+04 Console.WriteLine("{0:#0,}", num); // 64 Console.Writeline("{0:#.#;(#.##);0.00}", num); // 64354.2 num = -num; Console.WriteLine("{0:#.#;(#.##);0.00}", num); // (64354.23) num = 0.0;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Console.WriteLine("{0:#.#;(#.##);0.00}", num); // 0.00 num = 0.95; Console.WriteLine("{0:#%}", num); // 17%

StringBuilder class The System.String class can use the + operator to concatenate two strings. But this is inefficient when concatenating two different strings. The reason is that String objects in .NET are immutable, that is, the value cannot be changed once it is assigned to the string variable. When you concatenate another string to an existing one, you discard its old value and create a brand new string object which contains the result of the concatenation. Repeating this process several times leads to a performance penalty as new temporary objects will be created and old objects will be discarded. Consider the following example, where you concatenate all the numbers from 0 to 9999; int counter = 9999; string s = string.Empty; for (int i = 0; i n); foreach(var n in result) { Console.Write(n + " "); }

Example 2 1 2 3 4 5

Note that the first parameter of an extension method is not actually a parameter but is used to indicate which type to extend. Therefore the second parameter which accepts a lambda expression becomes the only parameter of method Select(). Inside the Select() method, we used a lambda expression that accepts one integer parameter and returns an integer value. Again, if you don't know lambda expressions then it might look wierd to you. What the lambda expression did was to retrieve every number and then add (return the value) to the query result. The code merely queries every number without modifying them. Let's modify the lambda expression inside the Select() method to do something more useful. COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

int[] numbers = { 1, 2, 3, 4, 5 }; var result = numbers.Select(n => n + 1); foreach(var n in result) { Console.Write(n + " "); }

Example 3 2 3 4 5 6

Our lambda expression parameter now retrieves a value from the numbers array, add 1 to its value, and add the new value to the query result. Most methods from the System.Linq return IEnumerable. This allows you to nest calls of LINQ methods. For example, consider the line of code below (ignore the new methods for now). The important thing is you can see how LINQ method calls can be nested or chained. var result = numbers.Where(n => n > 3).OrderBy(n => n).Select(n => n);

This lesson only shows how to use the Select() method but there are numerous LINQ methods that we will be looking at in the upcoming lessons. You will also see how to create more exciting results using the Select() method but for now, the important thing is that you know how to use the method syntax for querying data sources using LINQ. The method syntax is the real way the compiler does LINQ queries. The query expression syntax for querying from data sources is just a layer to simplify calling these extension methods. For example consider the query expression below: var result = from p in persons where p.Age >= 18 order by p.Name select p.FirstName + " " + p.LastName;

is translated at compile time into a series of calls to corresponding methods from the System.Linq namespace. The actual code uses the method syntax as show below: var result = persons.Where(p => p.Age >= 18) .OrderBy(p => p.Name) .Select(p => p.FirstName + " " + p.LastName);

You can see the chained method calls (I only aligned them for better readability). This was made possible because most of the LINQ methods return IEnumerable. After calling the Where() method, we used the OrderBy() method on the returned data, and then we used the Select() method on the returned data of OrderBy().

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Now that you know two ways to query data using LINQ, query expressions and method syntax; the question is which one should you use? I recommend using query expressions because it promotes declarative style of programming and it is simpler and easier to read than method syntax. But it is also important that you have knowledge of using method syntax because this is the way CLR read your query expression.

Deferred Execution There is one thing that you must know before we continue to the next lessons. You must know that LINQ uses deferred execution when performing queries. This simply means that the actual query is not executed until you iterate over or access each value from the result. Consider the following example: 1 int[] numbers = { 1, 2, 3, 4, 5 }; 2 3 int i = 3; 4 5 var result = from n in numbers 6 where n n).ToList();

Whichever method is executed last determines whether deferred execution will be used. The following table shows the methods of System.Linq and tells whether calling them will cause deferred execution. Method Execution Method Execution Distinct Deferred Reverse Deferred DefaultIfEmpty Deferred Select Deferred ElementAt Immediate SelectMany Deferred ElementAtOrDefault Deferred SequenceEqual Immediate Except Deferred Single Immediate First Immediate SingleOrDefault Immediate FirstOrDefault Immediate Skip Deferred GroupBy Deferred SkipWhile Deferred GroupJoin Deferred Sum Immediate Intersect Deferred Take Deferred Join Deferred TakeWhile Deferred Last Immediate ThenBy Deferred LastOrDefault Immediate ThenByDescending Deferred LongCount Immediate ToArray Immediate Max Immediate ToDictionary Immediate Min Immediate ToList Immediate OfType Deferred ToLookup Immediate OrderBy Deferred Union Deferred OrderByDescending Deferred Where Deferred Figure 1 - Methods Using Deferred Exection or Immediate Execution If the table above is too hard to remember, then you can just remember one rule on determining whether a query is deferred. If a query is expected to return a single result such as a single number or object, then it will be immediately executed. When a query will return an IEnumerable result, then most of the time it will use deferred execution. One technique to see if a query returns an IEnumerable result is by hovering over the var keyword of the query expression while you are in the Visual Studio editor. Look whether the help bubble shows that it is an IEnumerable type. If so, then the query will use deferred execution

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The select Clause The select clause in LINQ shapes the data to be included in the query result using projection. Projection is the process of transforming an object into a new form. The select clause of a LINQ query must be placed at the end of the query. You can do many kinds of manipulations to the currently queried value, retrieve certain properties of it, or create an annonymous type based on the queried object's properties. A typical LINQ query returns a collection that implements the IEnumerable interface where T is the resulting data type of the expression in the select statement. For example, if the select clause indicates to retrieve every person in a Person collection, then the returned collection implements the IEnumerable interface. If the select statement only selects the FirstName of every person, and assuming FirstName property is of type string, then the returned result implements the IEnumerable interface. You can then use a foreach loop to start the retrieving of results that will be yielded by the query expression. You can simply select the whole queried object by using the value of the range variable. This will select the queried object without any modifications or variations. int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var results = from number in numbers select number; foreach (var n in results) { Console.Write("{0, -2}", n); } 1 2 3 4 5 6 7 8 9 10

You can use different kinds of expressions that yield a result during selection. For example, you can query every number in an array of numbers and increment each of them by one. int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var results = from number in numbers select number + 1; foreach (var n in results) { Console.Write("{0, -2}", n); } 2 3 4 5 6 7 8 9 10 11

You can also select individual properties or combination of properties during the selection process. For example, you can only select the FirstName of every Person object from a List of Persons. List people = new List { new Person("Johnny", "Smith"),

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

new new new new

Person("Mark", "Lawrence"), Person("Jessica", "Fisher"), Person("Danny", "Mayer"), Person("Raynold", "Alfonzo")

}; var firstNames = from person in people select person.FirstName; Johnny Mark Jessica Danny Raynold

You can even combine different properties or other external data to the final value for the selection. For example, you can combine the FirstName property and the LastName property to select every person's full name. var fullNames = from person in people select person.FirstName + " " + .person.LastName; Johnny Smith Mark Lawrence Jessica Fisher Danny Mayer Raynold Alfonzo

The above select clause will select the person's FirstName, followed by a space, and then his/her LastName. You can use methods to manipulate the final value to be selected. For example, suppose you want to select every FirstName and convert them into all caps. var namesInCaps = from person in people select person.FirstName.ToUpper(); JOHNNY MARK JESSICA DANNY RAYNOLD

You can even select values not related to the data source being queried. For example, we can have a collection of indices and select a value from another collection or array. int[] indices = { 0, 1, 2, 3, 4 }; string[] words = { "Example1", "Example2", "Example3", "Example4", "Example5" }; var result = from index in indices select words[index]; Example1 Example2 Example3 Example4 Example5

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

We can create annonymous types during selection and include certain properties of each object. For example, suppose we have a Person object that has FirstName, LastName, Age, and Gender properties, and we only want to retrieve their FirstName and LastName, we can create a new annonymous type in the select clause which only includes the FirstName and LastName properties. var annonymous = from person in people select new { person.FirstName, person.LastName }; foreach (var p in annonymous) { Console.WriteLine(p.FirstName + " " + p.LastName); }

The type of the selected result would be an annonymous type having the properties included in the select clause. You can even create new properties based on the properties of the queried object. var results = from person in people select new { FN = person.FirstName, LN = person.LastName }; foreach (var p in results) { Console.WriteLine(p.FN + " " + p.LN); } Johnny Smith Mark Lawrence Jessica Fisher Danny Mayer Raynold Alfonzo

The select clause of the query expression above assigns the values of FirstName and LastName properties to new properties with different names. The type of these new properties are determined by the compiler based on the values being assigned to them thanks to type inference. These new properties are absorbed by the created annonymous type. var results = from person in people select new { Upper = person.FirstName.ToUpper(), Lower = person.FirstName.ToLower() }; foreach (var p in results) { Console.WriteLine("Upper={0}, Lower={1}", p.Upper, p.Lower); } Upper=JOHNNY, Lower=johnny Upper=MARK, Lower=mark Upper=JESSICA, Lower=jessica Upper=DANNY, Lower=danny Upper=RAYNOLD, Lower=raynold

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The select clause above assigns the FirstName converted to uppercase to a new property named Upper, and it's lowercase version to the new Lower property which are then included in an annonymous type. We then used this new properties inside a foreach loop. var results = from person in people select new { FullName = person.FirstName + " " + person.LastName }; foreach (var p in results) { Console.WriteLine(p.FullName); } Johnny Smith Mark Lawrence Jessica Fisher Danny Mayer Raynold Alfonzo

The above query's select clause creates a new property named FullName and assigns the combined value of each person's FirstName and LastName. The resulting annonymous type will have the FullName property which automatically gets the full name of the person. var results = from person in people select new { person.Age, FullName = person.FirstName + " " + person.LastName }; foreach (p in results) { Console.WriteLine("FullName={0}, Age={1}", p.FullName, p.Age); } FullName=Johnny Smith, Age=22 FullName=Mark Lawrence, Age=24 FullName=Jessica Fisher, Age=19 FullName=Danny Mayer, Age=21 FullName=Raynold Alfonzo, Age=25

The preceding query contains a select clause creates an annonymous type with a combination of an orginal property of each person and a new property FullName which contains the combined firstname and lastname of each person.

The Select Method The query method which is the direct equivalent of the select clause is the Select method. The Select method allows you to project the results of the query. We can use the Select method by passing a selector predicate which can be supplied using a lambda expression. As an example of the Select method, the following is a simple use of it where it retrieves every item in a collection. Consider the people variable is a collection of Person object. var result = people.Select(p => p);

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

A lambda expression is passed as the selector predicate for the method. The lambda expression has a single parameter p which will hold every Person object in the collection, and the right side of the lambda expression specifies what will be selected, in this case, the Person object itself. The following are more examples of using the Select method. The following are more varieties of using the Select method with different lambda expressions: 1. Select the FirstName of every person from people. var firstNames = people.Select(p => p.FirstName);

2. Select the combined FirstName and LastName of each person to form their fullname. var fullNames = people.Select(p => p.FirstName + " " + p.LastName);

3. Create an annonymous type that contains new property FullName which is the combined FirstName and LastName of each person. var annonymous = people.Select(p => new { FullName = p.FirstName + " " + p.LastName } );

Another overload of the Select method accepts a lambda expression which has two parameters, the first one is the queried element, and the second one is the index of that queried element from the data source. var personsWithIndex = people.Select((p, i) => new { Person = p, Index = i });

The following is its equivalent LINQ query: var personsWithIndex = from p in people select new { Person = p, Index = people.IndexOf(p) };

You can then print values of each person including their index. foreach (var p in personsWithIndex) { Console.WriteLine(String.Format("[{0}] {1}", p.Index, p.Person.FirstName)); } [0] John [1] Mark [2] Lisa

You can use the LINQ query syntax for a cleaner more readable code or you can directly call the LINQ methods using the query method syntax if you prefer to use lambda expressions.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The SelectMany Method When objects contains properties which holds a collection of objects, using the Select method is not applicable as it will return a "collection of collection" rather than all the items from those collection properties. We need to use the SelectMany method. The functionality of a SelectMany method is similar to a query expression with multiple from clauses. Let's say we have a class named Company, and it has a property named Employees which holds a collection of Employee type objects. A collection of Company objects can then be created. By using Select method, we can only query each company as seen below: var result = companies.Select(c => c);

What if we want to access or retrieve all of the employees for every company and flatten the result as a one whole list of items. Let's take a look at the following example: 1 class Company 2 { 3 public string CompanyName { get; set; } 4 public IEnumerable Employees { get; set; } 5 } 6 7 class Employee 8 { 9 public string FirstName { get; set; } 10 public string LastName { get; set; } 11} 12 13class Program 14{ 15 public static void Main(string[] args) 16 { 17 //Create some sample companies with employees 18 List companies = new List 19 { 20 new Company 21 { 22 CompanyName = "Company 1", 23 Employees = new List 24 { 25 new Employee { FirstName = "John", LastName = "Smith" 26}, 27 new Employee { FirstName = "Mark", LastName = "Halls" 28}, 29 new Employee { FirstName = "Morgan", LastName = "Jones" 30} 31 } 32 }, 33 new Company 34 { 35 CompanyName = "Company 2", 36 Employees = new List 37 { 38 new Employee { FirstName = "Winston", LastName = "Mars"

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

39}, 40 new Employee { FirstName = "Homer", LastName = "Saxton" 41}, 42 new Employee { FirstName = "Creg", LastName = "Lexon" } 43 } 44 }, 45 new Company 46 { 47 CompanyName = "Company 3", 48 Employees = new List 49 { 50 new Employee { FirstName = "Ben", LastName = 51"Greenland" }, 52 new Employee { FirstName = "Anthony", LastName = 53"Waterfield" } 54 } 55 } 56 }; 57 58 //Get All the FirstName of all employees 59 var firstNames = 60companies.SelectMany(c=>c.Employees).Select(e=>e.FirstName); 61 62 var lastNames = companies.SelectMany(c => c.Employees, (c, e) => 63e.LastName); 64 Console.WriteLine("FirstNames of all employees from the three companies."); foreach (var firstName in firstNames) Console.WriteLine(firstName); Console.WriteLine("\nLastNames of all the employees from the three companies."); foreach (var lastName in lastNames) Console.WriteLine(lastName); } }

Example 1 - Using the SelectMany Method FirstNames of all employees from the three companies. John Mark Morgan Winston Homer Creg Ben Anthony LastNames of all the employees from the three companies. Smith Halls Jones Mars Saxton

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Lexon Greenland Waterfield

We have defined two classes for this example. The first one named Company contains two properties named CompanyName and Employees. The Employees property has a type of IEnumerable which simply means that it allows you to store a collection of Employee objects to it. The Employee class was defined and has two simple properties to define a single employee. In the Main method, we created a collection of Company objects and initialize it to have three Company objects. Each Company objects was set a value for their CompanyName and a collection of Employee objects for their Employees property. Note that we are using the collection and object initializers here. Lines 52 to 54 uses the SelectMany method. Line 52 queries the FirstNames of all the employees from all the companies. companies.SelectMany(c => c.Employees).Select(e => e.FirstName);

This version of SelectMany method accepts only one argument. We pass a lambda specifying the property that the SelectMany will select. As the name of the method implies, "select many" means the method will select a collection of objects. In our example above, we selected the Employees property of every company which contains a collection of Employees. The SelectMany method will now return an IEnumerable. This allows us to nest another call to a plain Select method in which, we selected the first name of every employee from the result of the SelectMany method. There is another version of the SelectMany method which accepts two arguments, a collectionSelector and a resultSelector. If we are to rewrite line 52 using this different version of SelectMany, it will look like this. companies.SelectMany(c => c.Employees, (c, e) => e.FirstName);

Notice that we don't need to use the Select method to select a specific property of every Employee. The second argument handles that. The second argument accepts a lambda with two arguments. The first is the current item from the original collection, and the second is the current item from the selected property of the collectionSelector.

The where Clause You can filter the results of the query by using the where clause in a query expression. Following the where keyword is the condition (or conditions) that must be met by an item to be included in the results. The great thing with LINQ is that, you can use the available methods in .NET Framework to supplement your condition. This lesson will show you some examples on using the where clause to filter queried data.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can use relational operators to compare a value or property of an item into another value. For example, suppose we want to retrieve numbers which are greater than 5 from an array of numbers, we can do so using the following LINQ query. int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var greaterThanFive = from number in numbers where number > 5 select number;

The where clause states that the value of a number must be greater than 5 for it to be selected and included. We can even use logical operators for more complex conditions such as the following: var sixToTen = from number in numbers where number > 5 && number number > 5 );

The lambda expression's body is a single condition which tests the value of number if it is greater than 5. The following is another example which retrieves persons whose last name starts with 'R'. var startsWithR = people.Where( person => person.LastName.StartsWith("R") );

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can use another overloaded version of the method which accepts a lambda expression having two parameters. The first parameter represents every object from the collection, and the second parameter represents the index of that item in the collection. The following call to Where() method returns numbers whose index in its collection is even. var evenIndices = numbers.Where( (number, index) => index % 2 == 0 );

You can use the Where() method when you simply want to filter a collection using a specified condition.

The orderby Clause LINQ makes it easy for you to sort or modify the order of the results of the query. We can use the orderby clause and specify which value or property will be used as a key for sorting results. For example, suppose we have an array of numbers that we want to query and then arrange the results from highest to lowest, we can use the following query expression: int[] numbers = { 5, 1, 6, 2, 8, 10, 4, 3, 9, 7 }; var sortedNumbers = from number in numbers orderby number select number;

The query uses the orderby clause to order the results and we used the number or the actual object as the key for ordering those results. When you use the actual object, then their default behavior when being compared is used. For example, the above statement will compare the values of each queried integer and tests which is larger or smaller than the other one. The default behavior of the orderby clause is to sort the results from lowest to highest. We can explicitly command the query to sort it in ascending order by using the ascending keyword. var sortedNumbers = from number in numbers orderby number ascending select number;

To reverse its effect, that is, to sort values from highest to lowest, we can append the descending keyword in the orderby clause. var sortedNumbers = from number in numbers orderby number descending select number;

In cases where complex types are involved, you can use their properties as the key for ordering the results of a query. For example, suppose we have a collection of Person objects which has FirstName, LastName, and Age properties. We can sort the results from the youngest to the oldest person using the following query.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

var sortedByAge = from person in people orderby person.Age select person;

Again, we can use the descending keyword if you want to reverse the order of the query. We can also sort the results alphabetically based on each person's last name. var sortedByFirstName = from person in people orderby person.LastName select person;

What if two persons have the same last name? How will those items with the same values be sorted? We can specify multiple values in the orderby clause if you want to properly handle cases like these. var sortedByFnThenLn = from person in people orderby person.LastName, person.FirstName select person;

We seperate each soring key in the orderby clause by commas. The query above sorts the result based on every person's LastName, and if multiple persons have the same LastName, their FirstName will then be sorted. You can specify even more keys in orderby if for example, two persons still has the same FirstName. Note that using ascending or descending only affects one value in the orderby clause. For example, using a query like this with a descending keyword: var orderByResults = from person in people orderby person.LastName, person.FirstName descending select person;

only affects the property preceding it, in this case, FirstName. LastName will be ordered in ascending order by default. You can explicitly specify the order to avoid confusion. var orderByResults = from person in people orderby person.LastName ascending, person.FirstName descending select person;

A class can implement the IComparable interface which determines the default way an object can be sorted. The definition of the Person class is persented below showing an implementation of the IComparable interface. 1 class Person : IComparable 2 { 3 public string FirstName { get; set; } 4 public string LastName { get; set; } 5 public int Age { get; set; } 6 7 public Person(string fn, string ln, int age) 8 { 9 FirstName = fn; 10 LastName = ln;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

11 12 13 14 15 16 17 18 19 20 21 22 23}

Age = age; } public int CompareTo(Person other) { if (this.Age > other.Age) return 1; else if (this.Age < other.Age) return -1; else //if equal return 0; }

Example 1 Line 1 specifies that the method implements IComparable interface. We need to replace T with the type of the object to be compared, in this case, Person. Implementing that interface requires you to implement a method named CompareTo() which accepts the other object to be compared to this instance and returns an integer value which is the result of the comparison. Lines 14 to 22 defines that method and inside it, we tests whether the Age of this instance is greater than, less than, or equal to the other Person being compared. A value greater than 0 is returned if value from this instance is greater than the value of the other. A value less than 0 is returned if value of this instance is less than the other, and 0 if both values are equal. We can simply use 1 for greater than, -1 for less than, or 0 for equal. Now that a class implements the IComparable interface, we can simplify the LINQ query. Since we used the Age property inside the CopareTo method, not specifying a property as a key for ordering the results in a LINQ query will sort the results based on each person's age. List people = new List() { new Person("Peter", "Redfield", 32), new Person("Marvin", "Monrow", 17), new Person("Aaron", "Striver", 25) }; var defaultSort = from person in people orderby person select person; foreach (var person in defaultSort) { Console.WriteLine(String.Format("{0} {1} {2}", person.Age, person.FirstName, person.LastName)); } 17 Marvin Monrow 25 Aaron Striver 32 Peter Redfield

The OrderBy() and OrderByDescending() Methods

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The OrderBy() and OrderByDescending() methods in System.Linq are the corresponding LINQ methods of the orderby clause. The OrderBy() method sorts the results in ascending order based on a specified key, and the OrderByDescending() method is the opposite which sorts the results in descending order. We can pass a lambda expression specifying the key to be used for sorting. int[] numbers = { 5, 1, 6, 2, 8, 10, 4, 3, 9, 7 }; List people = GetPersonList(); var orderByQuery1 = numbers.OrderBy( number => number ); var orderByQuery2 = numbers.OrderByDescending( number => number ); var orderByQuery3 = people.OrderBy( person => person.FirstName ); var orderByQuery4 = people.OrderByDescending( person => person.Age );

The ThenBy() and ThenByDescending() Methods If you have multiple keys that you want to use, then you can use the ThenBy() and ThenByDescending() methods. For example, the LINQ query: var orderByQuery5 = from p in people orderby p.LastName, p.FirstName select p;

is equivalent to the following. var orderByQuery5 = people.OrderBy(p => p.LastName).ThenBy(p => p.FirstName);

You can use the ThenByDescending() method if you want the following keys to sort results in descending order. var orderByQuery6 = people.OrderBy(p=>p.LastName).ThenByDescending(p=>FirstName); var orderByQuery7 = people.OrderByDescending(p=>p.LastName) .ThenByDescending(p=>p.FirstName);

Note that ThenBy() and ThenByDescending() are methods of IOrderedEnumerable interface and the OrderBy() methods and the orderby clause returns a collection implementing this interface. Therefore, you must use OrderBy() or OrderByDescending() before calling ThenBy() or ThenByDescending().

Using an IComparer Interface Object An overloaded version of the four discussed ordering methods accepts a second comparer object argument. We can create a comparer class which implements the IComparer interface. class FirstNameComparer : IComparer

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

{ public int Compare(Person x, Person y) { return x.FirstName.CompareTo(y.FirstName); } }

The interface will require you to create an implementation for it's Compare() method which is similar to the CompareTo() method of the IComparable described eariler, except that it accepts two arguments which are the objects to be compared. We simply use the CompareTo() method of the String class which also returns and integer. We compared the FirstNames of the persons being compared . We can then pass an instance of this comparer as a second argument to the OrderBy, OrderByDescending, ThenBy, or ThenByDescending. var orderByQuery8 = people.OrderBy(person => person, new FirstNameComparer());

The second argument will then affect which key to use when ordering the results of a query. The above method call simply uses the whole person as the key, and with the help of the FirstNameComparer object, the method automatically orders the result by each person's FirstName property. An alternative for using methods for ordering in descending order and using the descending keyword is the Reverse() method. var orderByQuery9 = (from person in people orderby person.FirstName select person).Reverse(); var orderByQeury10 = people.OrderBy(person => person.FirstName).Reverse();

On the first example, the whole query is enclosed in parentheses to treat it as one and then we used the Reverse() method to the result of the query. The second example is the same as the first but uses the method syntax.

The let Clause The let clause allows you to store a result of an expression inside a query expression and use it on the remaining part of the query. A let clause is useful when the query is using an expression multiple times in a query or if you simply want to create an short alias to a very long variable or property name. List persons = new List { new Person { FirstName="John", LastName="Smith" }, new Person { FirstName="Henry", LastName="Boon" }, new Person { FirstName="Jacob", LastName="Lesley" } };

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

var query = from p in persons let fullName = p.FirstName + " " + p.LastName select new { FullName = fullName }; foreach (var person in query) { Console.WriteLine(person.FullName); }

Example 1 In the query expression in Example 1, the result of an expression to combine a person's FirstName and LastName properties and it store it to a variable for easy access. The rest of the query expression after the let clause can now use the variable containing the result of the expression. As you can see in the select clause of the query expression in Example 1, we used the newly created variable from the let clause and to create a property named FullName during projection. The let clause doesn't have an equivalent query method. The following rewrites the query expression above using the method syntax. var query = persons.Select(p => new { fullName = p.FirstName + " " + p.LastName }) .Select(p => new { FullName = p.fullName });

The following are more examples of using the let clause. int[] numbers = { 1, 2, 3, 4, 5 }; //Query Expression var query1 = from n in numbers let squared = n * n select squared; //Method Syntax var query2 = numbers.Select(n => new { squared = n * n }) .Select(n => n.squared);

Example 2 //Query Expression var query1 = from p in persons let isTeenager = p.Age < 20 && p.Age > 12 where isTeenager select new { p.FirstName, p.LastName }; //Method Syntax var query2 = persons.Select(p => new { isTeenAger = p.Age < 20 && p.Age > 12 }) .Where(p => p.isTeenager) .Select(p => new { p.FirstName, p.LastName });

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Example 3 The above query uses the variable created by the let clause as an argument to the where clause since the expression in the let clause is a boolean expression.

Joining Data Sources There are times where you want to combine values from different data sources into just one result. Of course those data sources must be related in some way. In LINQ, you can use the join clause or the Join() method to join multiple data sources with properties or fields that can be test for equivalency. With the join clause or the Join() method, you can do inner joins, group joins, or left outer joins. The concepts of joins in LINQ can be compared to joins in SQL. If you know how to do joins in SQL, then you may find the following concepts very familliar. Joins can be very hard to understand for a begginer so I will try my best to explain every concept as clear as possible. You will see how to use the join clause in the next lesson. Consider an Author database table containing names of authors and their respective AuthorId. Another table named Books which contains records of books with their titles and the AuthorId of the author that wrote them. One can join this two tables which means, each record of the result of a query is a combination of values from each of the table. A combined record for example, will have the Name of the author and the Title of the book. For two data sources to be joint together, each item or record must have a key that will be tested for equivalence. Only the two records which have equivalent keys will be combined. In our Authors and Books example, we can add an AuthorId field to both of the tables. An author can have an AuthorId that will uniquely identify him, while a book can have an AuthorId that determines which author wrote that book. In a join, there is an inner data source and an outer data source. The inner data source contains items which will be combined to the outer data source. Each of the inner item searches for a matching outer item and the two items are joined to create one new record. The following lessons discusses three types of joins. Inner joins allow you to combine two data sources and create a rectangular result. During an inner join, outer items that have no corresponding inner item are not included in the result set. Inner joins are the simplest and easiest type of join. Another type of join is the group join, which produces a hierarchical result set. It groups related items from one source by an item from another table. For example, you can place all the books written by a certain author into a group. Left outer joins is similar to an inner join as it also creates a rectangular result set, but it also includes outer items which has no corresponding inner item. You will learn more about each of this types of join in the following lessons. Note that you can also do joins using multiple from clauses but it will require you to properly structure your classes when defining them. For example, an Author can have a property named Books, which contains a collection of Book objects that the author writes. Join clause can be effectively used if both classes has no defined relationship. We just need to define the key property to be compared during the join operation. COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The join Clause - Doing an Inner Join Inner joins are the simplest type of join. This type of join returns a flat or rectangular result. It means that when you look at the result of the query, it would look like a table in which every cell has a value. Suppose we have two database tables named Authors and Books. The Authors table contains data of different authors. The Books table contains data of different books along with the ID of author that wrote a particular book. Joining the two tables using inner join will yield a rectangular result as seen in Figure 1. Author Book John Smith Little Blue Riding Hood John Smith Snow Black John Smith Hanzel and Brittle Harry Gold My Rubber Duckie Harry Gold He Who Doesn't Know His Name Ronald Schwimmer The Three Little Piggy Banks Figure 1 - A Rectangular Result An author can have multiple books assigned to him. In Figure 1, you can see that John Smith wrote three books, Harry Gold wrote two, and Ronald Schwimmer wrote only one book.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 2 - Inner Join For every item in the inner data source, it searches for its corresponding item in the outer data source and creates a combined item of that outer item and the inner item. After the first inner item finds its corresponding outer item, the second inner item is next and it also searches for its corresponding item in the outer data source. This repeats until all the inner items from the inner data source have found their corresponding item. To determine if two items are equal, both items must have a member or property which should have equal value. As you can see in Figure 2, Outer Item 4 was not included in the results. Any outer items that has no corresponding inner item is not included in the results. Same goes to an inner item that has no corresponding outer item. Let's take a look at the following example. The following code defines two classes, Author and Book. class Author { public int AuthorId { get; set; } public string Name { get; set; } } class Book { public int AuthorId { get; set; } public string Title { get; set; } }

As you can see in the above code, both Author and Book has the same AuthorId property. This will be the property that will determine the correspondence of a Book object to an Author object. Note that the properties doesn't need to have the same name but they should have the same data type. Example 1 creates Author and Book objects. Each book has its AuthorId pointed to a specific Author. 1 class Program 2 { 3 public static void Main(string[] args) 4 { 5 Author[] authors = new Author[] 6 { 7 new Author() { AuthorId = 1, Name = "John Smith" }, 8 new Author() { AuthorId = 2, Name = "Harry Gold" }, 9 new Author() { AuthorId = 3, Name = "Ronald Schwimmer" }, 10 new Author() { AuthorId = 4, Name = "Jerry Mawler" } 11 }; 12 13 Book[] books = new Book[] 14 { 15 new Book() { AuthorId = 1, Title = "Little Blue Riding Hood" }, 16 new Book() { AuthorId = 3, Title = "The Three Little Piggy 17Banks" }, 18 new Book() { AuthorId = 1, Title = "Snow Black" }, 19 new Book() { AuthorId = 2, Title = "My Rubber Duckie" },

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

20 new Book() { AuthorId = 2, Title = "He Who Doesn't Know His 21Name" }, 22 new Book() { AuthorId = 1, Title = "Hanzel and Brittle" } 23 }; 24 25 var result = from a in authors 26 join b in books on a.AuthorId equals b.AuthorId 27 select new { a.Name, b.Title }; 28 29 foreach (var r in result) 30 { 31 Console.WriteLine("{0} - {1}", r.Name, r.Title); 32 } } }

Example 1 John Smith - Little Blue Riding Hood John Smith - Snow Black John Smith - Hanzel and Brittle Harry Gold - My Rubber Duckie Harry Gold - He Who Doesn't Know His Name Ronald Schwimmer - The Three Little Piggy Banks

The query expression in lines 23-25 uses a join clause. The query expression first gets an Author object from the outer data source which is the authors. Then in the join clause, we retrieve a Book object from the inner source named books and test if the AuthorId of the retrieved author is equal to the books AuthorId. Note that the equals keyword was used instead of ==. The join clause can only test for equality. You cannot use operators such as > or < to compare keys. So to remind you that you can only do equality comparison, Microsoft created an equals keyword instead. If the current book's AuthorId is equal to an author's Author ID, then we can proceed to the select clause where the Name of the author and the Title of the book will be projected. Each of the book is iterated and compared to each author and all of the books with a corresponding author will be included in the results when execution of the query begins. Note that Jerry Mawler was not included in the results because he did not right any book, therefore, there is no item in the inner source that can be joined to him. Also, any book which AuthorId does not exist in the authors will not be included. The join clause, like any other clause, is translated during compilation into a call to the Join method. The query expression in Figure 4 can be translated into the following call to the Join method: var result = authors.Join(books, author => author.AuthorId, book => book.AuthorId, (author, book) => new { author.Name, book.Title } );

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This version of Join method performs an inner join. The method accepts four parameters. The first parameter accepts the inner data source, in this case, the books collection. The second parameter accepts a lambda expression that describes the outer key selector. It should have one parameter which will hold the every item from the outer source and then return the key that will be used for joining (we used the AuthorId as the key). The third parameter accepts a lambda expression which has one parameter that will hold every item from the inner data source, and returns the key to be compared to the outer source's key. Finally, the fourth parameter accepts a lambda expression with two parameters, the outer item and inner item that have matching keys. You can then use projection to create the type with the results from the two items.

The join Clause - Doing a Group Join With the join clause, you can also do group joins. A group join groups the items from the inner data source by their corresponding item from the outer data source. For example, all the books written by John Smith will be grouped together and all the books written by Harry Gold will have a separate group. The diagram below shows how group join works.

Figure 1 All the inner items which has a common key and has a matching key in the outer data source is grouped together to form one group. As you can see, the result of the group join is a collection of groups, each representing a group for a specified key. Again, for example, the key could be the author of the book. You can group a collection of books by authors and the result will be a collection of books grouped by authors. Any outer item that has no matching inner items will produced an empty group but still included in the result. Let's take a look at an example of doing a group join. We will define two classes named Author and Book. class Author { public int AuthorId { get; set; } public string Name { get; set; } } class Book {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

public int AuthorId { get; set; } public string Title { get; set; } }

The following code contains a query expression that uses a group join using the join clause. Author[] authors = new Author[] 1 { 2 new Author() { AuthorId = 1, Name = "John Smith" }, 3 new Author() { AuthorId = 2, Name = "Harry Gold" }, 4 new Author() { AuthorId = 3, Name = "Ronald Schwimmer" }, 5 new Author() { AuthorId = 4, Name = "Jerry Mawler" } 6 }; 7 8 Book[] books = new Book[] 9 { 10 new Book() { AuthorId = 1, Title = "Little Blue Riding Hood" }, 11 new Book() { AuthorId = 3, Title = "The Three Little Piggy Banks" }, 12 new Book() { AuthorId = 1, Title = "Snow Black" }, 13 new Book() { AuthorId = 2, Title = "My Rubber Duckie" }, 14 new Book() { AuthorId = 2, Title = "He Who Doesn't Know His Name" }, 15 new Book() { AuthorId = 1, Title = "Hanzel and Brittle" } 16 }; 17 18 var result = from a in authors 19 join b in books on a.AuthorId equals b.AuthorId into 20 booksByAuthor 21 select new { Author = a.Name, Books = booksByAuthor }; 22 23 foreach (var r in result) 24 { 25 Console.WriteLine("Books written by {0}:", r.Author); 26 27 foreach (var b in r.Books) 28 { 29 Console.WriteLine("---{0}", b.Title); 30 } 31 }

Example 1 Books written by John Smith: ---Little Blue Riding Hood ---Snow Black ---Hanzel and Brittle Books written by Harry Gold: ---My Rubber Duckie ---He Who Doesn't Know His Name Books written by Ronald Schwimmer: ---The Three Little Piggy Banks Books written by Jerry Mawler:

Take a look at the join clause in line 20. The join clause will join a book from the books data source to the authors data source in which the AuthorId of the book is equal to the AuthorId of

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

an author. The into keyword signifies the group join followed by a grouping variable. All the inner items' key that corresponds to an outer item's key will be grouped together and will be stored in the grouping variable. The select clause in line 21 projects the result to a new variable with an Author property and a Books property assigned with the group variable. The result of the query expression is a collection of groups of Books. The nested foreach loop in lines 23 to 31 shows the results of the query. Inside the first foreach loop, the name of the author is shown. After that, an inner foreach loop iterates through each of the Book in the author's Book property. Remember that this property contains the collection of books grouped together for a particular author. As you can see in the output, Jerry Mawler written no books so his Books property is empty, therefore, no books were shown. The GroupJoin method is the equivalent method of a join-group-by clause. The equilent query using the GroupJoin method is shown below: var result = authors.GroupJoin(books, author => author.AuthorId, book => book.AuthorId, (author, booksByAuthor) => new { Author = author.Name, Books = booksByAuthor });

The first parameter is the inner data source that will be joined to the outer data source. The second parameter is a delegate that accepts a lambda expression to determine the outer key to used for joining. The third parameter determines the inner key and the final parameter is used to create the group and project each result.

The join Clause - Doing a Left Outer Join Using LINQ's join clause, you can also perform a left outer join. Like an inner join, a left outer join also returns a flat result. An inner join omits any item that has no corresponding items from another data source. As an example, if an author wrote no book, then he will be omitted in the result of the query. The left outer join includes even the items that has no corresponding partner in the result. This is made possible using the DefaultIfEmpty method.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 1 - Left Outer Join Let's take a look at an example of doing a left outer join. 1 Author[] authors = new Author[] 2 { 3 new Author() { AuthorId = 1, Name = "John Smith" }, 4 new Author() { AuthorId = 2, Name = "Harry Gold" }, 5 new Author() { AuthorId = 3, Name = "Ronald Schwimmer" }, 6 new Author() { AuthorId = 4, Name = "Jerry Mawler" } 7 }; 8 9 Book[] books = new Book[] 10{ 11 new Book() { AuthorId = 1, Title = "Little Blue Riding Hood" }, 12 new Book() { AuthorId = 3, Title = "The Three Little Piggy Banks" }, 13 new Book() { AuthorId = 1, Title = "Snow Black" }, 14 new Book() { AuthorId = 2, Title = "My Rubber Duckie" }, 15 new Book() { AuthorId = 2, Title = "He Who Doesn't Know His Name" }, 16 new Book() { AuthorId = 1, Title = "Hanzel and Brittle" } 17}; 18 19var result = from a in authors 20 join b in books on a.AuthorId equals b.AuthorId into 21booksByAuthors 22 from x in booksByAuthors.DefaultIfEmpty(new Book 23{AuthorId=0,Title="None"}) 24 select new { Author = a.Name, x.Title };

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

25 26Console.WriteLine("{0, -20} {1}", "Author", "Book"); 27foreach (var r in result) 28{ Console.WriteLine("{0, -20} {1}", r.Author, r.Title); }

Example 1 Author John Smith John Smith John Smith Harry Gold Harry Gold Ronald Schwimmer Jerry Mawler

Book Little Blue Riding Hood Snow Black Hanzel and Brittle My Rubber Duckie He Who Doesn't Know His Name The Three Little Piggy Banks None

To do a left outer join using the join clause, you first need to group join the two data sources. You then perform another query by using the created groups as the data source. You need to callthe DefaultIfEmpty for each group so whenever a group contains no items, a specified default value will be provided. As you can see in the query expression in lines 19 to 22, the first two lines of the query expression performs a group join by querying every author object and joing every book object which has an equal AuthorId property as the queried author's AuthorId property. The next line performs another query by using the grouped result of the first query as the data source. Notice that we call the DefaultIfEmpty method of the group to yield a default value if the group is empty. The DefaultIfEmpty method accepts one argument, which is an instance of an object which has a similar type as every items of the group. Since each group in our query contains Book items, we created new instance of the Book class and specified some default values for its properties using objection initialization syntax. Based on our data sources, Jerry Mawler (AuthorId 4) has no corresponding book from the books data source. If we simly used an inner join, Jerry Mawler will be gone in the results, but since we used left outer join, Jerry Mawler was included and as you can see in the output of Figure 2, the default value you specified was shown as his book. There is no direct equivalent of a left outer join when you want to use the method syntax. Doing a left outer join using the method syntax requires the combination of the GroupBy method and the SelectMany method. var result = authors.GroupJoin(books, author => author.AuthorId, book => book.AuthorId, (author, booksByAuthor) => new { Author = author, Books = booksByAuthor }) .SelectMany(x=>x.Books.DefaultIfEmpty(new Book{AuthorId = 0,Title = "None"}),

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

(x, y) => new { Author = x.Author.Name, y.Title });

The GroupJoin method simply groups each books by author and projects a new type with an Author property assigned with the author and Books property assigned with the group of books he wrote. We then nested a call to the SelectMany method. The SelectMany method here accepts two parameters. The first is the collection selector which selects item from the result yielded by the GroupJoin method. Notice that we call the DefaultIfEmpty method so if the Books property of an item is empty, then a default set of values specified will be used. The second parameter is the result selector and through here, you can project the final result of the query.

The join Clause - Doing a Left Outer Join Using LINQ's join clause, you can also perform a left outer join. Like an inner join, a left outer join also returns a flat result. An inner join omits any item that has no corresponding items from another data source. As an example, if an author wrote no book, then he will be omitted in the result of the query. The left outer join includes even the items that has no corresponding partner in the result. This is made possible using the DefaultIfEmpty method.

Figure 1 - Left Outer Join Let's take a look at an example of doing a left outer join.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Author[] authors = new Author[] 1 { 2 new Author() { AuthorId = 1, Name = "John Smith" }, 3 new Author() { AuthorId = 2, Name = "Harry Gold" }, 4 new Author() { AuthorId = 3, Name = "Ronald Schwimmer" }, 5 new Author() { AuthorId = 4, Name = "Jerry Mawler" } 6 }; 7 8 Book[] books = new Book[] 9 { 10 new Book() { AuthorId = 1, Title = "Little Blue Riding Hood" }, 11 new Book() { AuthorId = 3, Title = "The Three Little Piggy Banks" }, 12 new Book() { AuthorId = 1, Title = "Snow Black" }, 13 new Book() { AuthorId = 2, Title = "My Rubber Duckie" }, 14 new Book() { AuthorId = 2, Title = "He Who Doesn't Know His Name" }, 15 new Book() { AuthorId = 1, Title = "Hanzel and Brittle" } 16}; 17 18var result = from a in authors 19 join b in books on a.AuthorId equals b.AuthorId into 20booksByAuthors 21 from x in booksByAuthors.DefaultIfEmpty(new Book 22{AuthorId=0,Title="None"}) 23 select new { Author = a.Name, x.Title }; 24 25Console.WriteLine("{0, -20} {1}", "Author", "Book"); 26foreach (var r in result) 27{ 28 Console.WriteLine("{0, -20} {1}", r.Author, r.Title); }

Example 1 Author John Smith John Smith John Smith Harry Gold Harry Gold Ronald Schwimmer Jerry Mawler

Book Little Blue Riding Hood Snow Black Hanzel and Brittle My Rubber Duckie He Who Doesn't Know His Name The Three Little Piggy Banks None

To do a left outer join using the join clause, you first need to group join the two data sources. You then perform another query by using the created groups as the data source. You need to callthe DefaultIfEmpty for each group so whenever a group contains no items, a specified default value will be provided. As you can see in the query expression in lines 19 to 22, the first two lines of the query expression performs a group join by querying every author object and joing every book object which has an equal AuthorId property as the queried author's AuthorId property. The next line performs another query by using the grouped result of the first query as the data source. Notice that we call the DefaultIfEmpty method of the group to yield a default value if the group is empty. The DefaultIfEmpty method accepts one argument, which is an instance of an object

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

which has a similar type as every items of the group. Since each group in our query contains Book items, we created new instance of the Book class and specified some default values for its properties using objection initialization syntax. Based on our data sources, Jerry Mawler (AuthorId 4) has no corresponding book from the books data source. If we simly used an inner join, Jerry Mawler will be gone in the results, but since we used left outer join, Jerry Mawler was included and as you can see in the output of Figure 2, the default value you specified was shown as his book. There is no direct equivalent of a left outer join when you want to use the method syntax. Doing a left outer join using the method syntax requires the combination of the GroupBy method and the SelectMany method. var result = authors.GroupJoin(books, author => author.AuthorId, book => book.AuthorId, (author, booksByAuthor) => new { Author = author, Books = booksByAuthor }) .SelectMany(x=>x.Books.DefaultIfEmpty(new Book{AuthorId = 0,Title = "None"}), (x, y) => new { Author = x.Author.Name, y.Title });

The GroupJoin method simply groups each books by author and projects a new type with an Author property assigned with the author and Books property assigned with the group of books he wrote. We then nested a call to the SelectMany method. The SelectMany method here accepts two parameters. The first is the collection selector which selects item from the result yielded by the GroupJoin method. Notice that we call the DefaultIfEmpty method so if the Books property of an item is empty, then a default set of values specified will be used. The second parameter is the result selector and through here, you can project the final result of the query.

More LINQ Examples Now that you have learn some basic LINQ querying including how to select, filter, and order results of a query, let's take a look at more examples combining the concepts of the past lessons and introducing some new LINQ features as well. The examples will allow you to more familiar to more techniques of using LINQ. I will show the LINQ query and its corresponding method calls to LINQ methods. var query1 = from p in people orderby p.LastName where p.Age >= 18 select new { p.FirstName, LN = p.LastName }; var query1 = people.OrderBy(p => p.LastName).Where(p => p.Age >= 18) .Select(p => new { p.FirstName, LN = p.LastName });

The queries above are equivalent and they both represent sombe combinations of selecting, filtering and ordering results. We must take note of the second version where we used the actual COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

LINQ methods. The dot operator was used immediately after the end of the previous method. The methods or members you can call after the dot operator depends on the value returned by the previous method. Since LINQ methods returns a result implementing IEnumerable, you can nest or cascade method calls one after the other. The final result to be stored in the result variable depends on the final results of the last LINQ method call, in the case above, the Select method. The second version presented can also be called the dot notation style. var query2 = from p in people orderby p.LastName, p.FirstName where p.Age >= 18 && p.LastName.StartsWith("A") select new { FullName = p.FirstName + " " + p.LastName }; var query2 = people.OrderBy(p=>p.LastName).ThenBy(p=>p.FirstName) .Where(p=>p.Age >= 18 && p.LastName.StartsWith("A")) .Select(p=> new {FullName = p.FirstName + " " + p.LastName });

The query selects persons from the people collection ordering the results by LastName and then by FirstName, and whose Age is greter than or equal 18 and has a LastName which starts with A. The query then selects an annonymous type containing the FullName of the person that met the condition in the where clause. We can use the let clause to define another range variable inside a query and assign it with an expression or property of the original range variable. The following shows you an example of using the let clause. var query2 = from p in people let lastName = p.LastName where lastName.StartsWith("A") select lastName; var query2 = people.Select(p=> new { p, lastName = p.LastName }) .Where(pln => pln.lastName.StartsWith("A")) .Select(pln => pln.lastName)

We defined a new range variable and assigned the LastName property of the original range variable. We can now use the new range variable in the following clauses. The second version that uses dot notation style shows how we can do the same functionality as the first version. The let clause in a LINQ query is just similar to a Select method. We called the Select method at the very beginning so the following methods will know the modifications made. We can use multiple data sources and compare each of their values against each other. The following uses two from clauses that retrieves values from two integer arrays. var query3 = from x in n1 from y in n2 where x == y select x; var query3 = n1.Intersect(n2);

The query first retrieves a value from n1. The retrieved value will then be compared to each value in n2 thanks to the second from clause and the where clause. The where clause states that

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

only retrieve the value of x that has an equal value in any of the elements of y. This is also called intersections where only values that both exists in two sets will be returned in the result set. We can simply use the Intersect method to do the same thing. Another example is an object that contains a property containing a collection of more objects. Imagine our Person class having a property named Siblings which is a list of siblings (List) of a person. We can select every sibling of a person and even specify a condition for the selection. var query4 = from p in people from s in p.Siblings where s.Age < p.Age select new { FullName = p.FirstName + " " + p.LastName, SiblingName = s.FirstName + " " + s.LastName }; var query4 = people.SelectMany(p => p.Siblings.Select(s => s).Where(s => s.Age < p.Age));

The first from clause retrieves a Person from the list of Person objects. The second from clause retrieves every Person object in the current Person's Sibling property. The first from clause will only continue to retrieve the next Person object after the second from clause is finish retrieving all of the items from the Siblings property. The where and select clauses in the query also executes for every item retrieve by the latter from clause from its corresponding data source. The second version of the query uses the SelectMany method. You can see that inside it is a lambda expression selecting every Person from people and we accessed each person's Sibling property and used another Select method followed by a Where method inside the SelectMany method.

LINQ Aggregate Methods LINQ has aggregate operators or methods that allows you to perform mathematical calculations based on the values of all the elements in a collection. We will learn here the different aggregate operators that will simplify the way you do most common tasks involving sets or collections of values. Example of what aggregate operators can do is automatically getting the sum, average, min, max, and how many elements a collection has.

The Count and LongCount Methods We can determine the number of elements a collection or array has by using the Count and LongCount methods. The Count method simply counts the number of elements of a collection. For collections containing a very huge number of elements, we can use the LongCount method instead. The following example shows the use of the Count operator. int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 }; Console.WriteLine("numbers has {0} elements.", numbers.Count());

An overload of both Count and LongCount allows you to pass a predicate that will determine which elements to include in the counting. Consider the following example:

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Console.Write("Number of even numbers in the collection: {0}", numbers.Count(n => n % 2 == 0));

The lambda expression inside the overloaded Count method specifies the condition that an element must meet for it to be included in the counting.

The Min and Max Methods The Min and Max methods returns the minimum and maximum values from a collection respectively. The parameterless versions of this method is very simple and returns the expected results. int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 }; Console.WriteLine("Min = {0}\nMax = {1}", numbers.Min(), numbers.Max());

For complex objects that does has no implementation for IComparable, that is, a default behavior when being compared, we can use an overloaded of the Min() and Max() methods which accepts a predicate that specifies the key or expression to be used. List people = GetPersonList(); //Assume the method returns a collection of Person objects Console.WriteLine("Youngest Age is {0}", people.Min( p=>p.Age )); Console.WriteLine("Oldest Age is {0}", people.Max( p=>p.Age ));

We passed a lambda expression specifying that we should use the Age property of each person as a key and therefore, the Min and Max methods returned the minimum and maximum age of all the persons in the collection.

The Average Method The Average method is obviously used for determining the average of numeric values. The average is the sum of all the values of every element divided by the number of elements. int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 }; Console.WriteLine("Average = {0}", numbers.Average());

Like Min and Max methods, the Average method has an overloaded version which accepts a predicate to determine which key to use when obtaining the average of a complex object such as our example Person class. List people = GetPersonList(); Console.WriteLine("Average age of all the persons"); Console.WriteLine("Average = {0}", people.Average( p => p.Age ));

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The lambda expression states that we use the Age of every person as the key on getting the average value. Therefore, the method Average results to the average Age of all the persons in the collection.

The Sum Method The Sum method is also a very simple to understand operator which simply gets the overall sum of all the values of elements in a collection. int[] numbers = { 7, 2, 6, 1, 7, 4, 2, 5, 1, 2, 6 }; Console.WriteLine("Sum = {0}", numbers.Sum);

Again, we can use an overloaded version which accepts a predicate that will determine a key from a complex object such as Person. List people = GetPersonList(); Console.WriteLine("Total age of all the persons"); Console.WriteLine("Total = {0}", people.Sum(p => p.Age));

The expression inside the Sum method instructs the method to add the age of every person together.

The Aggregate Method The Aggregate method is a more flexible version of method Sum. Instead of limiting you to just summing up values in a collection, you can define a predicate with two parameters, the first one being the first nubmer or the previous result, and the second one is the second or next number to participate the calculation. int[] numbers = { 1, 2, 3, 4, 5 }; Console.WriteLine( numbers.Aggregate( (n1, n2) => n1 + n2 ) );

The Aggregate method contains a two-parameter lambda expression and inside its body, we add the two numbers. Initially, n1 will contain the first value of the array, and n2 will have the second value. It will be added and stored to n1. The next value (third value) will then be stored to n2, and will be added again to n1 whose result will be stored to n1 and n2 aquiring the value of the next element. This repeats until n2 has the value of the last element. The result of the above call to Aggregate is similar to Sum method since we add every numbers. A great thing about the Aggregate method is we can choose the operator we want on the calculation. Below is a modification of the previous code where the Aggregate returns the overall product of the collection using the multiplication operator. int[] numbers = { 1, 2, 3, 4, 5 };

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Console.WriteLine( numbers.Aggregate( (n1, n2) => n1 * n2 ) );

You can even create complex expressions like this. int[] numbers = { 1, 2, 3, 4, 5 }; Console.WriteLine( numbers.Aggregate( (n1, n2) => (n1 / 2) + (n2 / 2) ) );

The Aggregate method above halves the values before adding them to each other. Another overload of the Aggregate method accepts a seed which is simple the one that will take the first slot in the calculation. int[] numbers = { 1, 2, 3, 4, 5 }; Console.WriteLine( numbers.Aggregate( 1, (n1 , n2) => n1 + n2 ));

Notice that Aggregate now has two parameters, the first one being the seed and the second one is the predicate specifying how to process each pair of values. Since we specified a seed of 1, the calculation will start at 1 plus whatever the first value of the array is. Since the first value of the array in the code above is 1 and the specified seed is 1, then the first calculation will be 1 + 1 (seed + first). A third overload of the Aggregate method accepts a third argument which specifies the formatting of the result. Console.WriteLine( numbers.Aggregate( 1, (n1, n2) => n1 + n2, n => String.Format("{0:C}", n)));

The third parameter is another lambda expression that will format the result into currency format. Using these aggregate methods is a great help for programmers as it saves development time and is really easy to use once you mastered them.

LINQ to SQL LINQ to SQL is a powerful tool which allows developers to access databases as objects in C#. With LINQ to SQL, you are able to use LINQ query operators and methods instead of learning SQL. LINQ to SQL has an API for connecting and manipulating database. LINQ queries and calls to the API methods are then translated to SQL commands which are executed to provide changes or to retrieve queries from the database. LINQ to SQL is a more modern way of accessing database using C# and .NET. Please do note that LINQ to SQL is only applicable when you are using SQL Server as your database. We will be using the Northwind database as our sample database. If you are using the free Visual C# Express then we need to access the actual database file which has a .mdf file extension. If you installed the Northwind database correctly, the file can be found in C:\SQL Server 2000 Sample Databases. If the file extension is not visible, go to Control Panel, choose Folder

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Options and click the View tab, and uncheck "Hide extensions for known file types", then click OK. We will be using the Northwind.mdf database file. Database files are created with .mdf extensions whenever you create a database in SQL Server. SQL Server Express 2008 has a default folder for storing database files and it is located at C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data. So if you executed the scripts for creating the Northwind database as instructed in the first lessons, then you can also find a copy of Northwind.mdf here. We can proceed if once you have possession of the Northwind.mdf file. Visual Studio has a great tool for generating LINQ to SQL classes with the use of Object Relational Designer. You can simply drag and drop tables there and Visual Studio will automatically create the neccessary classes the corresponds to each tables and rows of the specified table and database. You will then see the tables with properties corresponding to its columns or fields. Arrows will also be visible representing relationships between tables.

Figure 1 - Object Relational Designer showing tables, fields and relationships. Classes will be created that represents the rows of each table.For example, we have an Employees table. Visual Studio will automatically singularize the table's name and an object named Employee will be created that will represent each row or records of the particular table.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

A corresponding class of type Table of the System.Data.Linq namespaces will be created for every table included in the LINQ to SQL Designer. The TEntity is replaced with the class of the row it contains. For example, the Employees table will have a corresponding class of Table class. An object of that class will then be created containing a collection of objects for each of its rows or records. Table implements IQueryable interface of the System.Linq namespace. When a LINQ queries an object that implements this interface and obtains results from a database, the results are automatically stored to the corresponding LINQ to SQL classes. For related tables which are connected to each other via foreign keys, for each foreign key a table has, Visual Studio creates a corresponding property with the type and name similar to each row of the table the foreign key points to. Additionally, for a table whose primary key(s) are used as a foreign key by other tables, for each of those foreign tables, a property is also created. This additional properties allow you to call the properties of the foreign table of a current table. For example, two tables named Employees and Companies table both have CompanyID fields. The CompanyID is the primary key of the Companies table, and the CompanyID field of the Employees table is a foreign key pointing to the CompanyID of the Companies table. When Visual Studio creates the corresponding row class for each table, it will also consider the foreign keys. The Employee class for the Employees table will have an additional Company property since one of its columns points to the Companies table. The Company class of the Companies table will have an additional Employee property because the Employees table points to the Categories table. LINQ to SQL also creates a DataContext class which inherits from the System.Data.Linq.DataContext. This class will be responsible for connecting the program and the database. The objects created for each table that you include in the LINQ to SQL designer becomes a property of this class. Visual Studio will automatically create the DataContext in a format DataContext where is the name of the database. For example, using our Northwind database, a NorthwindDataContext will be created with properties corresponding to each tables we have included. These properties contains collections of objects representing the rows of each table. For example, our NorthwindDataContext class will have a Employees property which corresponds to the Employees table. This property is a collection of Employee objects representing each rows of the table. The next lesson will show you an example of using LINQ to SQL and connecting your application to the Northwind database using this technology.

Querying a Database with LINQ to SQL We will be creating a Windows Forms Application that allows as to you to query and view records from a particular table using LINQ to SQL classes, SQL Server 2008, and the Northwind sample database. You will learn how to use the Object Relational Designer to generate LINQ to SQL Classes and how to use them in your code.

Creating LINQ to SQL Classes

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Create a new Windows Forms Application and name it LinqToSqlDemo. Once a project is created, we need to add a LINQ to SQL file. Click the Add New Item button in the toolbar and find LINQ to SQL Classes from the list of templates. Name it Northwind and click the Add button.

Once you click the Add button, you will land on the Object Relational Designer containing nothing as off now.

The Toolbox now also contains components used for creating classes and adding relationships. But since we will generate a class from an existing table in a database, we wont be using the components in the Toolbox. A DBML file (Database Markup Language) with extension .dbml will also be created and shown in the Solutions Explorer. Expanding that node will show two more files representing codes for the layout and the actual classes that will be generated. Double clicking the DBML file will also bring you to the Object Relational Desinger.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

We need to use the Database Explorer window in Visual C# Express. If you are using the full version of Visual Studio, you need to open the Server Explorer window instead. If it is not visible, go to Views > Other Windows > Database Explorer. Open the Database Explorer window and click the Connect to Database icon.

You will be presented with the Choose Data Source Dialog which asks which type data source to use for the connection. Choose SQL Server Database File. Checking the check box allows you to always choose the specified type of data source when you want to add another one.

You will be presented by another window asking for the type of data source and the location of the database files. You can also specify which SQL Server account to use but if you are using an administrator windows user account, then you can simply leave the default option. You can also click the Advanced button to edit more advanced settings about the connection.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Click the Browse button and browse for the Northwind.mdf file. If you have installed it already, it will be located at C:\SQL Server 2000 Sample Databases. Choose the file and click Open. Be sure that the file is not used by other programs. We then need to test the connection. Click Test Connection button and if everything is working properly, you will receive the following message.

The Northwind.mdf will now appear as a child node of the Data Connections in the Database Explorer window. Expand the Northwind.mdf node to be presented with folders representing the different components of the database. Expand the Tables folder to see the different Tables of the Northwind database. We need to drag tables from the Database Explorer window to the Object Relational Designer's surface. For this lesson, drag the Employees table to the Object Relational Designer.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Visual Studio will prompt you whether to copy the Northwind.mdf database file since it will detect that it is located outside your project folder. Clicking Yes will copy the Northwind.mdf file from the origincal location to your project folder. Also note that everytime you run your program, the database file will also be copied to the output directory. You will learn later how to modify this behavior.

After clicking Yes, The Object Relational Designer will now show a class diagram representing a generated class that will hold values of each row in the Employees table. The name of the class is a singularized version of the Table's name. A property with an appropriate type is created for every column in the dragged table. You will see these properties in the Object Relational Designer. If a property conflicts with the name of the class, then it will be numbered. For

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

example, if the class' name is Employee and it has a column named Employee as well, then the column's corresponding property will be named Employee1.

As soon as you drag a table to the Object Relational Designer, the DataContext class for the coresponding database will be created. Since we used the Northwind database, the generated DataContext class will be named NorthwindDataContext. Clicking a blank space in the Object Relational Designer will allow you to edit the properties of the DataContext class using the Properties Window. You can also change the properties of the created row class and properties of its members. But leaving the default names and settings for the classes is recommended. If you are curious about the generated classes and wan't to take a look at its implementation, go to Solution Explorer and expand the node for the created DBML file. You will be presented with two files. Double click the one with .designer.cs extension. You will then see how the classes for your tables and DataContext was defined. You should always save the DBML file before using it in your application.

Using LINQ to SQL Classes Once the required LINQ to SQL classes have been successfully generated, we can now use them in our application. For our GUI, we will be using a DataGridView control to display the queried records. Head back to the Windows Forms Designer. Drag a DataGridView control from the Toolbox's Data cetegory to the form. Set the DataGridView's Dock property to Fill so it will take up all the space of the form. Then resize the form to a larger size so it will properly show all the records that we will query.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

We will be using the following code: 1 using System; 2 using System.Linq; 3 using System.Windows.Forms; 4 5 namespace LinqToSqlDemo 6 { 7 public partial class Form1 : Form 8 { 9 public Form1() 10 { 11 InitializeComponent(); 12 } 13 14 private void Form1_Load(object sender, EventArgs e) 15 { 16 NorthwindDataContext database = new NorthwindDataContext(); 17 18 var employees = from employee in database.Employees 19 select new 20 { 21 employee.EmployeeID, 22 employee.FirstName, 23 employee.LastName,

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

24 25 26 27 28 29 30 31 32}

employee.BirthDate, employee.Address, employee.Country }; dataGridView1.DataSource = employees; } }

Double click the Form's title bar in the Designer to generate a handler for the form's Load event. Add the codes in lines 16-29. The code at line 16 creates a new NorthwindDataContext object. This will be used to access the tables of the database and the rows each table contain. Lines 1827 uses a LINQ query which access the NorthwindDataContext's Employees property containing each record for employee. The select clause of the query only selects some of the properties of every employee. Line 29 uses the DataGridView's DataSource property and assigns the result of the query as it's data source. When you run the program, you will see all the records from the Employees table.

Lines 18-27 is a simple LINQ query that retrieves several properties of every employee in the Employees database. You can perform different LINQ queries that suit your needs. For example, we can modify the LINQ query in 18-27 to only show employees who live in USA. var employees = from employee in database.Employees where employee.Country == "USA" select new

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

{ employee.EmployeeID, employee.FirstName, employee.LastName, employee.BirthDate, employee.Address, employee.Country };

You can provide controls, for example, a combo box containing different countries, and modify the query based on the selected country in the combo box. For more LINQ techniques, you can review the lessons for the basics of LINQ querying.

Modifying Database with LINQ to SQL Mapping the database tables and its records to their corresponding LINQ to SQL classes makes it even easier to manipulate databases. Once LINQ to SQL classes are generated, you can do the modification directly to objects of those class. For adding, the DataContext class offers the InsertOnSubmit and pass the new object of the row class to add. When deleting, we can use the DeleteOnSubmit and pass the specified object to delete. We can directly modify the properties of an object representing a record if we want to update it. All of this operations will not immediately affect the actual tables and records in the database. We need to call the SubmitChanges method of the DataContext class first. To access an element of the property representing the Table, we can use the ElementAt method which accepts an integer index and returns the corresponding record object. Our example application will allow the user to check details of every record, and allows you to add, delete and update records using LINQ to SQL and the method offered by the DataContext and Table classes. For the following example the we will create, we will be using a sample database containing a single table named Persons which contains some records. Download Sample Database Once you downloaded the rar file, open it and extract the database file inside it to a location that you can easily find. We will create an application that queries one person at a time and allows us to move through every record using navigation buttons. The appilcation will also allow the user to add, delete, or update records. You will see how easy this can be done using LINQ to SQL classes. Create a new Windows Forms Application and name the project LinqToSqlDemo2. Create a LINQ to SQL and name it Sample.dbml.. Go to the Database Explorer and click the Connect to Database button. Choose Microsoft SQL Server Database file and click OK then browse for the location of the Sample.mdf file you have downloaded. It will now show up in the Database Explorer as a seperate node. Open the nodes and inside the Tables node, drag the Persons table to the Object Relational Designer. Click Yes to accept the option to copy the database file to your project folder.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will now be presented with a class inside the Object Relational Designer named Person.

As you can see, it only has several properties. We will now create the GUI that we will use to present details of each records and also to add or delete records. Add the neccessary controls and their corresponding text as shown in the GUI below. The numbers will indicate the corresponding names to be used by the controls.

Number Name 1 firstButton 2 prevButton COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Number Name 3 nextButton 4 lastButton 5 idTextBox 6 firstNameTextBox 7 lastNameTextBox 8 ageTextBox 9 addButton 10 deleteButton 11 updateButton Set the idTextBox's ReadOnly property to true so it can't be modified as it will show a primary key value. You can also set the StartPosition property of the form to CenterScreen. The buttons above will be used to move to the first, previous, next, or last record in the Persons table. The text boxes will be used to display the values of every field of the current person. The buttons below are used to Add, Delete, and Update records. Clicking the addButton will clear the textboxes so it can accept new values from the user to be added to the table. Clicking the deleteButton will delete the current record being shown. Clicking updateButton will update the record being shown if some of its details were modified. We will be using the following code for our application: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

using using using using

System; System.Collections.Generic; System.Linq; System.Windows.Forms;

namespace LinqToSqlDemo2 { public partial class Form1 : Form { private int currentIndex; private int minIndex; private int maxIndex; private bool addPending; private SampleDataContext database; private IEnumerable persons; public Form1() { InitializeComponent();

COMPILED BY:

database = new SampleDataContext(); persons = from p in database.Persons select p; currentIndex = 0;

Bsc ABDULRAHIM ALI ATHUMAN

27 minIndex = 0; 28 maxIndex = persons.Count() - 1; 29 30 DisableButtons(); 31 32 addPending = false; 33 } 34 35 private void Form1_Load(object sender, EventArgs e) 36 { 37 ShowPersonInfo(currentIndex); 38 } 39 40 private void firstButton_Click(object sender, EventArgs e) 41 { 42 ShowPersonInfo(minIndex); 43 currentIndex = minIndex; 44 DisableButtons(); 45 } 46 47 private void lastButton_Click(object sender, EventArgs e) 48 { 49 ShowPersonInfo(maxIndex); 50 currentIndex = maxIndex; 51 DisableButtons(); 52 } 53 54 private void prevButton_Click(object sender, EventArgs e) 55 { 56 ShowPersonInfo(--currentIndex); 57 DisableButtons(); 58 } 59 60 private void nextButton_Click(object sender, EventArgs e) 61 { 62 ShowPersonInfo(++currentIndex); 63 DisableButtons(); 64 } 65 66 private void addButton_Click(object sender, EventArgs e) 67 { 68 if (addPending == false) 69 { 70 ClearFields(); 71 int newIDnewID = persons.Count() == 0 ? 1 : 72 persons.Last().PersonID + 1; 73 idTextBox.Text = newIDnewID.ToString(); 74 addButton.Text = "Done"; 75 addPending = true; 76 } 77 else 78 { 79 try 80 { 81 //Create new person 82 Person newPersonnewPerson = new Person(); 83 newPersonnewPerson.PersonID = maxIndex + 1;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

84 newPersonnewPerson.FirstName = firstNameTextBox.Text; 85 newPersonnewPerson.LastName = lastNameTextBox.Text; 86 newPersonnewPerson.Age = Int32.Parse(ageTextBox.Text); 87 88 //Add new Person 89 database.Persons.InsertOnSubmit(newPersonnewPerson); 90 database.SubmitChanges(); 91 maxIndex++; 92 currentIndex = maxIndex; 93 DisableButtons(); 94 MessageBox.Show("Successfully added to database.", 95 "Success", 96 MessageBoxButtons.OK, 97 MessageBoxIcon.Information); 98 addButton.Text = "Add"; 99 addPending = false; 100 } 101 catch 102 { 103 MessageBox.Show("Failed to add new record to database. 104Make sure " + 105 "that every field is not empty and in 106a correct " + 107 "format", "Failed", 108 MessageBoxButtons.OK, 109MessageBoxIcon.Error); 110 } 111 } 112 } 113 114 private void deleteButton_Click(object sender, EventArgs e) 115 { 116 try 117 { 118 119database.Persons.DeleteOnSubmit(persons.ElementAt(currentIndex)); 120 database.SubmitChanges(); 121 122 maxIndex--; 123 124 if (currentIndex > maxIndex) 125 currentIndex--; 126 127 MessageBox.Show("Successfully removed from the database.", 128"Success", 129 MessageBoxButtons.OK, MessageBoxIcon.Information); 130 131 ShowPersonInfo(currentIndex); 132 DisableButtons(); 133 } 134 catch 135 { 136 MessageBox.Show("Unable to delete.", "Error", 137 MessageBoxButtons.OK, 138MessageBoxIcon.Error); 139 } 140 }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

141 142 private void updateButton_Click(object sender, EventArgs e) 143 { 144 try 145 { 146 Person modifiedPerson = persons.ElementAt(currentIndex); 147 modifiedPerson.FirstName = firstNameTextBox.Text; 148 modifiedPerson.LastName = lastNameTextBox.Text; 149 modifiedPerson.Age = Int32.Parse(ageTextBox.Text); 150 151 database.SubmitChanges(); 152 MessageBox.Show("Update success!", "Success", 153 MessageBoxButtons.OK, 154MessageBoxIcon.Error); 155 } 156 catch 157 { 158 MessageBox.Show("Error on updating.", "Error", 159 MessageBoxButtons.OK, 160MessageBoxIcon.Information); 161 } 162 } 163 164 private void ShowPersonInfo(int index) 165 { 166 if (persons.Count() == 0) 167 { 168 ClearFields(); 169 MessageBox.Show("Nothing to show.", "Error", 170 MessageBoxButtons.OK, 171MessageBoxIcon.Error); 172 return; 173 } 174 175 Person currentPerson = persons.ElementAt(index); 176 177 idTextBox.Text = currentPerson.PersonID.ToString(); 178 firstNameTextBox.Text = currentPerson.FirstName; 179 lastNameTextBox.Text = currentPerson.LastName; 180 ageTextBox.Text = currentPerson.Age.ToString(); 181 } 182 183 private void DisableButtons() 184 { 185 if (persons.Count() minIndex && currentIndex < maxIndex) { firstButton.Enabled = true; prevButton.Enabled = true; nextButton.Enabled = true; lastButton.Enabled = true; } } private void ClearFields() { idTextBox.Text = String.Empty; firstNameTextBox.Text = String.Empty; lastNameTextBox.Text = String.Empty; ageTextBox.Text = String.Empty; firstNameTextBox.Focus(); } } }

Example 1 Lines 10-15 declares some required variables that we will use throughout our program. Line 10 declares a variable that will hold the current index of the person to show. Line 11-12 declares variables that will be used to hold the minimum and maximum possible indices so we can avoid IndexOutOfRangeExceptions and disable specific navigation buttons. Line 13 will be used by the addButton later as we will see. Line 14 declares a SampleDataContext object which is the corresponding DataContext of the Sample database. We will use this object to call methods for adding, deleting, updating, and retrieving records from the tables of the Sample database. Line 15 declares an object of type IEnumerable which will hold all the person records queried from the database. Recall the results of a LINQ query implements IEnumerable so we can simple use this type in the declaration of the object in line 15. This is so we don't have to query all the records everytime we need to use them. We can simple use this object throughout our program. We will first discuss the utility methods that will be used by the application. The ClearFields method (line 205-212) simply clears every text field and sets the focus to the firstNameTextBox. Method DisableButtons (line 172-203) will be used to disable navigation buttons once the currentIndex reached the minimum or maximum bounds. This is to prevent the user to move when no more elements are available to show. It also checks if there is 1 or 0 records left so it can disable all the navigation buttons to prevent the user from moving. The ShowPersonInfo method (153-169) accepts an index and retrieve a Person object using the specified index. Lines COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

155-161 first checks if the number of elements or records in the Persons property is empty using the Count method. If so, we print an error message and return to the caller to prevent the other codes from of the method from executing. In line 163, we used the ElementAt method of the Persons property to retrieve the right object using the index as an argument to the ElementAt method. We then displayed the properties of the retrieved Person object to their corresponding text boxes. Now let's go inside the Form1's constructor (Line 17 - 33). Line 21 creates an instance of the SampleDataContext so it can now be used to perform operations to the database. Lines 22-23 is a simple LINQ query that selects all the person from the Persons property of the SampleDataContext instance which contains every record of person. We then set the currentIndex to 0 to indicate the program should initially show the first record. Lines 27-28 sets the minIndex and maxIndex which holds the minimum and maximum indices respectively. We simply assign the value 0 to the minIndex. The maxIndex was calculated by obtaining the number of person records in the Persons property and subtracting by 1 because indices are 0based. We called the DisableButtons method that we created to disable the buttons that the user won't need as of now. We also set the addPending to false. This will be used by the handler of the addButton later. Go back to the desinger and double click the form's title bar to generate an event handler for its Load event (lines 35-38). Inside the handler, we called the ShowPersonInfo and passed the current value of the currentIndex which is 0 to show the first record in the text boxes. We will now add the Click event handlers for the navigation buttons. In the Designer, double click the firstButton. Use the codes in lines 42-44 for the event handler. The first line calls the ShowPersonInfo and passing the minIndex value to show the very first record. The value of currentIndex is then set back to the value of minIndex. We called the DisableButtons to disable the firstButton and prevButton. The event handler for lastButton (47-52) is the same as the firstButton's only that it shows the details of the last record using the maxIndex variable. The prevButton and nextButton's Click event handlers (54-64) are also nearly identical. The both call the ShowPersonInfo method and pass the currentIndex to show the records at that specified index. We also increment or decrement the currentIndex right inside the method call to adjust value of the currentIndex. The event handler for addButton (66-106) has the following functionality. The addbutton will have two states. The first state is when addPending is set to false. Clicking the button in this state will first clear the text boxes(line 70). It will then calculate the next possible PersonID to assign for the soon to be added new reacord (71). The calculated new id is displayed to the appropriate text box. The Text of the addButton is changed to "Done" to indicate the it is waiting for the user to finish providing values for each fields of the new person to add. The addPending variable is then set to true to transfer the button to its second state. The second state of the addButton is when it is waiting for the user to finish providing values. When the user hits again the addButton while in this state, it will now execute commands to add the new record to the database. Note that everything that will be used to add the new record to the database is enclosed in a try block so we can catch exceptions that might occur including FormatExceptions or ChangeConflictExceptions which is thrown by the SubmitChanges method when it encounters

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

an error. Lines 81-85 creates a new Person object and assign its properties to values of the text boxes. Line 88 uses the Table.InsertOnSubmit method and passes the newly created Person object so it will be added to the database when the DataContext.SubmitChanges method is executed. The SubmitChanges method is called in line 89 to submit that new change that was made, that is, that adding of a new record to the list of Persons in the Persons table. Line 90 adjusts the value of maxIndex by incrementing it by one since the number of records was increased by 1. We set the currentIndex to the value of the maxIndex, called DisableButtons method, and print a success message telling that the adding of the new record to the database was successful. We changed back the button's caption to "Add" and set the addPending to false so it can accept again new records once clicked. The catch block simply shows an error message telling the user that problems occur while adding the new record to the database. The handler for the deleteButton (108-131) also encloses it's code in a try block to prevent uncaught exceptions that might occur. Line 112 uses the DeleteOnSubmit method which accepts the object to delete from table. To retrieve the right Person object to delete, we used the ElementAt method and passed the currentIndex to it. Since a change was made, we called the SubmitChanges method to send the change to the actual database table. We decrement the maxIndex by 1. We also adjust the currentIndex to an appropriate value. Decreasing the maxIndex while while the currentIndex will make currentIndex greater than the maxIndex. Therefore, we also decrement the value of the currentIndex to match the maxIndex. A person right before the deleted person will then be displayed. The updateButton will be used to update the values of the currently displayed person. When a person's details is displayed, you can change the values in the text boxes, and press the updateButton to update the corresponding record in the database. The handler for the updateButton (133-151) creates a Person that will hold a reference to the currently displayed Person. The properties of this Person is then changed using the new values that the user may have provided. We then immediately called the SubmitChanges method to send the changes and update the corresponding record in the database table. Note that there is no method such as UpdateOnSubmit which could have been similar to the two methods we have seen. You simply modify the values of the properties and call the SubmitChanges method. Download Project: LinqToSqlDemo2

LINQ to XML The .NET Framework provided us with several techniques for accessing and manipulating an XML file. In the past, you can use the XmlReader or the different XML Document Object Model classes such as XmlDocument, XmlElement, and XmlComment. You can also use XML querying languages such as XPath or XQuery to select specific elements in an XML document. The problem is, you have to know this languages which really has nothing to do with C#. That's where LINQ to XML comes in. With LINQ to XML, you can use the LINQ operators to query, manipulate, and create XML documents. If you want to learn the old and non-LINQ way of manipulating and creating XML documents, this site already offers some tutorials for those.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Let's take a look at a simple example of using LINQ to XML on a preexisting XML file containing some data.

30 Male

25 Male

22 Female

27 Male

35 Male

Example 1 - A Sample XML File Open Visual Studio and create a new Console Application project and name it LinqToXmlPractice. Right click the solution in the Solution Explorer and add a new item. Choose Xml file from the list of template and name it sample.xml. Replace the contents of that file with the one from Example 1. Our sample.xml file contains the XML markup that we will try to query. If you are unfamiliar with XML, there are many good tutorials in the internet that will teach you its concepts. There is also a quick introduction to XML that can be found in this site. The XML file contains one root element named Persons. It contains multiple child elements named Person. Each child element has a name attribute and contains yet another set of child elements, the Age and Gender elements. Now let's write some LINQ query to retrieve, let's say, the names of every person in the XML Document. Open up Program.cs and add using statement for the System.Linq.Xml namespace. using System.Linq.Xml;

Inside the Main method, write the following: XDocument doc = XDocument.Load(@"..\..\sample.xml");

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

var names = from d in doc.Root.Elements("Person") select d.Attribute("name").Value; Console.WriteLine("Names of every person from the XML file."); foreach (var name in names) { Console.WriteLine("{0}", name); }

Example 2 - Using LINQ to query XML elements Names of every person from the XML file. John Smith Mike Folley Lisa Carter Jerry Frost Adam Wong

Full explanation for the codes will be in the upcoming lessons. But for now, you can see how easy it is to get any data you want from the elements of an XML document.

Creating an XML Document Using LINQ to XML If you played with the XML Document Object Model classes to create XML documents from scratch, it will be easy for you to migrate to a brand new set of classes which allows you to create XML elements in a much more natural and easier way. These classes are located inside the Sytem.Linq.Xml namespace. The classic way of loading an XML document is by using the XmlDocument class from the System.Xml namespace. XmlDocument doc = XmlDocument.Load("myXmlFile.xml");

There is no difference if you are going to use the newer XDocument class. XDocument doc = XDocument.Load("myXmlFile.xml");

So what makes this new classes have besides from having shorter names compared to their older versions? The answer is functional construction. With functional construction, you don't need to declare the XML DOM elements one by one. You can simply use the overloaded constructors of each X class to suit your needs. This can be seen clearer by looking at an example. By using the old System.Xml's XML DOM classes, the following code is used to create a simple XML file. //A new XML Document XmlDocument doc = new XmlDocument(); //Xml Declaration XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "utf-8", "yes"); //Attach declaration to the document

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

doc.AppendChild(declaration); //Create a comment XmlComment comment = doc.CreateComment("This is a comment"); //Attach comment to the document doc.AppendChild(comment); //Create root element XmlElement root = doc.CreateElement("Persons"); //Attach the root node to the document doc.AppendChild(root); //Create a Person child element XmlElement person1 = doc.CreateElement("Person"); //Add an attribute name with value John Smith person1.SetAttribute("name", "John Smith"); //Crate Age element XmlElement person1Age = doc.CreateElement("Age"); person1Age.InnerText = "30"; //Create Gender element XmlElement person1Gender = doc.CreateElement("Gender"); person1Gender.InnerText = "Male"; //Attach Age and Gender element to the Person element person1.AppendChild(person1Age); person1.AppendChild(person1Gender); //Attach Person child element to the root Persons element doc.DocumentElement.AppendChild(person1); //Create another Person child element XmlElement person2 = doc.CreateElement("Person"); //Add attribute name with value Mike Folley person2.SetAttribute("name", "Mike Folley"); //Crate Age element XmlElement person2Age = doc.CreateElement("Age"); person2Age.InnerText = "25"; //Create Gender element XmlElement person2Gender = doc.CreateElement("Gender"); person2Gender.InnerText = "Male"; //Attach Age and Gender element to the Person element person2.AppendChild(person2Age); person2.AppendChild(person2Gender); //Attach second Person child element to the root Persons element doc.DocumentElement.AppendChild(person2); //Save the constructed XML into an XML file doc.Save(@"C:\sample1.xml");

Example 1 - Using XML DOM classes to create a file The above code will produce the following XML:

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN



30 Male

25 Male

Now let's take a look at using the new LINQ to XML classes to create the very same XML markup. XDocument doc = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XComment("This is a comment"), new XElement("Persons", new XElement("Person", new XAttribute("name", "John Smith"), new XElement("Age", new XText("30")), new XElement("Gender", new XText("Male"))), new XElement("Person", new XAttribute("name", "Mike Folley"), new XElement("Age", new XText("25")), new XElement("Gender", new XText("Male"))))); doc.Save(@"C:\sample2.xml");

Example 2 - Using LINQ to XML classes to create an XML document As you can see, using the XML DOM classes to construct an XML document requires you to declare each component and attach each element to their proper parents one by one. Using the LINQ to XML classes, you can see the every part of the XML document you will create is instantiated inside the constructor of every classes. These method of creating XML markup is called functional construction. Each LINQ to XML class' constructor accepts arguments that may serve as child elements or values of the element it represents. For example, the XElement has the following overload of its constructor: XElement(XName name, params object[] content)

The first parameter accepts the name of the element. You can simply pass a string as the name and it will automatically be converted to an XName instance. The second parameter is special because it allows you to pass any number of different kinds of objects such as an XText, XAttribute, or an XElement that will be a child element of that current XElement. Other LINQ to XML class only accepts one argument such as XComment and XText which both accept a string argument that represents the text they will render. The following table shows some of the LINQ to XML classes you can use together what part of an XML document they represent.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Class Description XDocument Represents an XML Document XDeclaration Represents an XML Declaration XElement Represents an XML Element XAttribute Represents an attribute of an XML Element XComment Represents an comment XText Represents the inner text of an XML element. Figure 1 - LINQ to XML Classes For example, if you want to create an element named Person with an name attribute of value John Smith, here's the code to do that. var personElement = new XElement("Person", new XAttribute("name", "John Smith"));

If you want to add a child element for that person, simply add another argument to the constructor of XElement. var personElement = new XElement("Person", new XAttribute("name", "John Smith"), new XElement("Age", new XText("30")));

The child argument has a name of Age and the next argument to its constructor is it's inner text represented by the XText class. You can also see in Example 2 how every XElement argument was indented. This is to make it look more like the way we indent XML elements. You can already see how the XML output will look like simply by looking at the code. At the end of Example 2 is a call to the XDocument.Save method. This method allows you to save the constructed XML which is currently in memory, into an external XML file. The method accepts a string argument which represents the file path of the file. If the file does not exist, then it will be created. If the file is already there, it will be overwritten. There are other overloads of this method, but for now, this version is sufficient to save the constructed XML to a file.

“MORE TUTORIALS COMING SOON”

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

C# ADO.NET AND DATABASES Databases and ADO.NET Most of the applications today uses some sort of data storage. Perhaps the only applications I can imagine that doesn't use some kind of storage for its data are those small and very simple applications. An application can have many kinds of data sources such as a simple text file, an XML file, and a database. Databases are typically used when storing different kinds of data such as the name, address, age, gender, and occupation of a person, musics, pictures, and many more. A database is a collection of different kinds of data structured into tables consisting of fields and records. Most real world applications today uses databases to store informations. Relational databases contain data which are organized and linked to each other. Relational databases contains one or more tables interconnected to each other. Tables consists of rows and columns. In a database, the rows represents each record. For example, on a database containing records of employee, one row represents a record of an employee. The columns represents the fields or attributes. For example, an Employee has a FirstName field, a LastName field, and an Age field. You can also create relations between multiple tables. For example, an Employee table could have a field called City_ID. Then another table called Cities contains fields City_ID and the CityName. You can connect these two tables to form a relation. Structured Query Language (SQL) is the most popular and perhaps the standard way of communicating to a database. It has commands you can use for retrieving, updating, adding, and deleting data from the database. It also allows you to create and modify databases and tables and create relationships between different tables. Database Management Systems (DBMS) such as Microsoft SQL Server allows you to quickly access data from a database. It contains different tools such as tools for querying, creating, deleting and updating a database. Most DBMS provides you a graphical interface for creating common tasks. Other examples of DBMS are Access, Oracle, and MySQL. ADO.NET is part of the .NET framework technology that allows you to access and modify data from different data sources. It supports many types of data sources such as Microsoft SQL Server, MySQL, Oracle, and Mircrosoft Access. The .NET Framework provides a number of data providers that you can use. These data providers are used to connect to a data source, executes commands, and retrieve results.The following lessons uses Windows Forms Applications as a project type for connecting to databases although you can easily incorporate what you will learn in other areas such as ASP.NET.

SQL Basics Before you deal with accessing and modifying databases, you first need to know the basics of SQL (Structured Query Language). This is the language used for querying databases. SQL is simple and easy to understand. SQL is not only used for querying data, it can pretty much do

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

anything from creating, updating, and deleting databases and tables. Since this site is not about SQL, we will only tackle those that will be needed in the upcoming lessons.

Creating Database and Tables You can create database using the following syntax. Please do note that SQL is case insensitive. So it doesnt matter if you write the keywords in lowercase. CREATE DATABASE ;

The is the name that you want to give to your database. Here's an example. CREATE DATABASE MyDatabase;

For us to store a Database, we need to create a table. We use the following syntax. CREATE TABLE (

. . .

);

, ,

Again is the name of the table we want to create. Inside the parentheses are a list of columns and their data type. The data types that you will commonly used is listed below. Data Type Description Example int integer data -3, 1, 12, 57 char(n) fixed length string where n is the maximum length 'hello', 'goodbye' varchar(n) variable length string where n is the maximum length 'hello', 'goodbye' datetime stores date and time Jan 1, 2010 3:00PM date stores date only Jan 1, 2010 time stores time only 3:00PM money stores monetary data 123.45 You might notice that char(n) and varchar(n) seems to be the same. char(n) is fixed and once you give size to it, it will take up memory depending on that size. If the size you have given is 100, and the string you store only has 3 characters, then char(n) will still use memory for 100 characters. varchar(n) is different. It only takes up what is needed. Also note that character strings are enclose inside single quotes. Let's create an example table that can store the FirstName, LastName and Age of employees.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

CREATE TABLE Employees ( EmployeeID int primary key, FirstName varchar(100), LastName varchar(100), Age int );

Notice that we added the primary key word after the data type of EmployeeID. This will signify that EmployeeID will be the primary key of the Employees table. A primary key is a value that identifies a row or record. Primary key must be unique for each of the record. We used EmployeeID as the primary key and not, for example, the FirstName, because multiple employees could have the same name therefore, that will conflict the rule that primary keys need to unique. The FirstName and LastName fields have a data type of varchar(100), that means the length has a maximum of 100 characters. You can also specify a primary key field to be an identity field. An identity field is a field that is automatically being assigned with a value when adding new records. For example, if we add a new record, it will automatically assigned with value 1, and this will be incremented by 1 as new records are added. The following modifies our previous example to make the EmplyeeID as the identity column. CREATE TABLE Employees ( EmployeeID int identity primary key, FirstName varchar(100), LastName varchar(100), Age int );

We simply used the identity keyword that will specify a column as the identity column. You can use the following SQL Command to Delete an existing table. DROP TABLE Employees;

This will delete the Employees table and all of its records.

Inserting Records We use the following syntax to insert records to a table.. INSERT INTO

VALUES (, , ... , );

The
is the name of the table where we want to insert our data into. Inside the parenthesis after VALUES, you list all the values for each of the field of the table. The order of data is important. You must follow the order defined when you created the Table. Let's add some records to our Employee Table.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

INSERT INTO Employees VALUES (1, 'John', 'Smith', 21); INSERT INTO Employees VALUES (2, 'Mark', 'Mayer', 23); INSERT INTO Employees VALUES (3, 'Alvin', 'Minsky', 27);

This will insert the 3 employees to our Employees table. Note the order of the parameters. Our table definition defines that the first parameter is the EmployeeID, the second is FirstName, LastName and then the last is the Age. Again, the EmployeeID must be unique because that is the primary key. Another form of the INSERT TO statement allows you to explicitly indicate the columns that you want to add with values. The following only adds values to FirstName and LastName fields. INSERT INTO Employees (FirstName, LastName) VALUES ('John', 'Smith');

Note that the number and type of values should match the number and type of fields that have been specified.

Deleting Records To delete a record, we used this syntax. DELETE FROM
WHERE ;

The condition tells what record you want to delete. Most of the time, you use the primary key field to delete a record. As an example, Let's delete John from our table. DELETE FROM Employees WHERE EmployeeID = 1;

The above statement reads as "Delete a record from the Employees table whos EmployeeID is equal to 1. Since John has an EmployeeID of 1, he is deleted from the table.

Updating Records If you want to change a value of a field or fields of an existring record, you can do that using the following syntax. UPDATE
SET = WHERE ;

For example, if you want to change the FirstName of Mark, use the following code. UPDATE Employees SET FirstName = 'Marco' WHERE EmployeedID = 2;

We set the FirstName field of the employee with EmployeeID that is equal to 2 to 'Marco'. If you want to change the values of multiple fields, then you can seperate them with commas. UPDATE Employees SET FirstName = 'Marco', LastName = 'Miller' WHERE EmployeedID = 2;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Querying Records We can use the SELECT statements to query or get data from our database. The syntax is as follows: SELECT , , ... FROM ;

For example, if we want to query all the FirstNames of the employee, we cas write this code: SELECT FirstName FROM Employees; FirstName John Mark Alvin

You can select multiple columns just like this. SELECT FirstName, LastName FROM Employees; FirstName LastName John Smith Mark Mayer Alvin Minsky

You can also use the WHERE keyword to only select those that meet the condition. SELECT FirstName, LastName FROM Employees WHERE FirstName = 'John'; FirstName LastName John Smith

To Select Everything from the table, you can use the * character. SELECT * FROM Employees EmployeeID FirstName 1 John 2 Mark 3 Alvin

LastName Smith Mayer Minsky

Age 21 23 27

You can arrange the result by using the ORDERBY keyword. SELECT FirstName, LastName FROM Employees ORDERBY FirstName FirstName LastName Alvin Minsky John Smith Mark Mayer

If you want to arrange the records in descending order, you can use the DESC keyword. SELECT FirstName, LastName FROM Employees ORDERBY FirstName DESC FirstName LastName Mark Mayer John Smith

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Alvin

Minsky

SQL alone, is a very big language. There is many more not discussed in this lesson. Now that you have learned the basics of SQL, we can now proceed to how we can access databases from our application.

Installing SQL Server 2008 Express We will be using Microsoft SQL Server 2008 Express as our main data source. SQL Server is already installed if you have Visual C# Express or Visual Studio 2010, provided that you didn't uncheck the option of installing SQL Server during installation. We will also be using the SQL Management Studio Express which is a program that contains graphical tools for creating databases. Even if SQL is already installed via the installation of Visual C# Express, the SQL Management Studio might still not be installed. To check if it is already installed, go to Start > All Programs > Microsoft SQL Server 2008 and check if SQL Management Studio is there. If not, then you have to download and install it first. Don't worry though if you don't have SQL Management Studio as I will present two ways on creating and manipulating databases; using SQL Management Studio and using the simple command prompt. If you don't have SQL Server 2008 and SQL Management Studio, then you can download and install it manually. The following shows you step by step guide on how to do download and install them to your computer. First step is to download an all-in-one package containing Microsoft SQL Server 2008 and Microsoft SQL Server Management Studio using the following link. Download Microsoft SQL Server 2008 When you arrive at the download page, click the SQL Server 2008 R2 Express tab.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will now choose which system you are currently using as described earlier. Choose the type of system you have (32-bit or 64-bit).

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will be taken to another page. Choose your language desired using the drop down list and then click the download button.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Once you have downloaded the installer, execute it to begin installation. The following shows step by step instructions on how to install Microsoft SQL Server 2008 R2 Express Edition and the SQL Server Management Studio.

The installer will begin extracting required files for the installation. Wait for it to finish.

The SQL Server Installation Center will show up. Be sure the "Installation" is selected. Since we will be installation SQL Server, choose the first option.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Wait for the installation to start up.

In this window, read the License Terms and check the first check box to accept it. Click Next to proceed to the next step.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Wait again for the installer to load the required installation files.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The setup will check for your system for required components. If it sees a missing component, then you need to download and install them first. Click Next if no errors were detected.

This window allows you to select different features and the installation path for your SQL Server Express. Leave everything as is and click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This window asks for the name of the database instance that will be used by SQL Server Express. You can name it anything you want but it is recommended to leave it to its default name of SQLEXPRESS.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The following window might be automatically skipped during installation. It shows the disk space requirements needed by the program. Click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This window specifies the accounts that will have access to the database. Change the account name of the first row to NT AUTHORITY\SYSTEM and the second row to NT AUTHORITY\LOCAL and be sure that both has their Startup Type as Automatic.Click Next.

This window allows you to choose an authentication type. Choose Mixed Mode to allow both Windows Authentication and database authentication. You will also need to provide a password for the sa (System Administrator Account) which will have full credentials and control with the databases. Please make sure that you remember that password that you will type. You can also add more users to your database, but for this tutorial, we won't be needing that. Click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This window gives you an option to send error reports to Microsoft so they can fix it. It is up to you to check the option or you can simply ignore this and click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The setup will now begin installing Microsoft SQL Server 2008 R2 Express. Wait for the installation progress to finish. Then click Next.

Congratulations, you have now successfully installed Microsoft SQL Server 2008 R2 Express. Click Close. Close the SQL Server Installation Center if it is still open.

Creating a Sample Database and Table We will create a database containing a table with several records that we will use in the following lessons. This lesson presents two ways of creating a database and table. If you don't have SQL Management Studio installed, then we can use the command prompt and the sqlcmd Utility. You also need to use the SQL commands we have discussed. If you would like to use SQL Management studio instead, then you can skip to the next section.

Connecting to Microsoft SQL Server Using sqlcmd Utility Let's start by opening command prompt. In Windows XP, click Start > Run and then type cmd. In Vista and Windows 7, open up start and type cmd in the search box. Press enter to open up command prompt. Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Users\YourName>

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The command that will allow us to connect to SQL Server is the sqlcmd. This will execute the sqlcmd Utility which allows you to feed SQL commands to a connected server instance. There are also a lot of options you can specify when using this command. The following table enumerates the useful ones that we can use. Option Description -U The user login ID. If this is not specified SQL uses Windows Authentication mode. The user password. If -P is not specified and -U is specified, then sqlcmd will prompt -P you for the password. -S Specifies the name of the instance of a server that we will be connecting to. Figure 1 - sqlcmd Options If you followed the tutorial on how to install Microsof SQL Server 2008 Express, note that we specified a name for the server instance. We used SQLEXPRESS as the name of the instance. This is important to know when connecting to a database. We have also indicated a password for the sa account. We will be using that password to enter the server using the sa account. The following shows how to connect to the SQLEXPRESS server using the sa account. C:\Users\YourName>sqlcmd -S .\SQLEXPRESS -U sa -P mypassword

We used the -S option to specify that we will use the SQLEXPRESS server instance. When specifying server instances, we also need to specify the computer name, or the ip address of where the actual server containing the server instance resides. If you don't know a lot of networking and the concept of ip addresses, then we can connect to the SQLEXPRESS instance located in your own computer using the name of your machine, or by simply typing a dot. It is then followed by a backslash and then the name of the server instance. We also indicated the username and password using the -U and -P options. We used the sa account and the password that we have provided when we installed SQL server. Alternatively, if you can't remember the password, simply omit the -U and -P options and the sqlcmd will use Windows Authentication. You may recieve some issues regarding limited persmissions if you are not logged in with a windows administrator account. C:\Users\YourName>sqlcmd -S .\SQLEXPRESS

This will use the credentials of the currently logged in windows user. Logging in as sa gives you full control with the database. In a real world scenario, you will have to create multiple accounts with limited privelages to prevent malicious users from compromising the contents of the database. After you have typed the command, press enter and if everything went well, you can see a prompt waiting for you to type an SQL command. C:\Users\YourName>sqlcmd -S .\SQLEXPRESS 1>

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Creating a Database Using sqlcmd Utility We will be creating a database named University which will be consisting of the Students table. To create the database, type the SQL command shown below. 1> CREATE DATABASE University

If you press enter, nothing will happen, and sqlcmd will wait for another line of SQL command to be typed. To execute the command we need to type GO and press enter. 1> CREATE DATABASE University 2> GO

You need to wait for a few seconds for the command to take effect. If everything is successful, no error messages will show up and the prompt will reset back to 1. 1> CREATE DATABASE University 2> GO 1>

Creating a Table Using sqlcmd Utility We will now create the Students table which will contain the details about several students in the university. First, we need to ensure that the database we are using is the University database that we recently created. Type the following commands. 1> USE University 2> GO

Press enter to change the database that we are currently working to the University database. Also, a message will show up that will confirm the change. Let us now create the Students table. Type the following SQL commands. 1> CREATE TABLE Students 2> ( 3> StudentID int identity primary key, 4> FirstName varchar(50), 5> LastName varchar(50), 6> Gender varchar(10), 7> Age int, 8> Address varchar(50) 9> ) 10> GO 1>

The created table has 6 columns. The first one is the StudentID which we declared as the primary key and an identity column and having a type of int. We also declared FirstName, LastName,

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Gender, Age, and Address with their appropriate SQL data types. Excuting this command creates our new table.

Adding Records Using sqlcmd Utility Now that we created our table, let's add several rows or records of students. The following table shows some fictional student data that we will add in our table. StudentID FirstName LastName Gender Age Address 1 Edward Lyons Male 17 Spencer Street 2 Jimmie Vargas Male 18 Blue Bay Avenue 3 Monica Ward Female 16 Mapple Street 4 Joann Jordan Female 17 Spencer Street 5 Cheryl Swanson Female 17 Wacky Street 6 Clara Webb Female 18 Spooner Street 7

Zack

Norris

Male

19 Blue Bay Avenue

8 9 10

Randall Jessica Oscar

May Cole Manning

Male 18 Golden Street Female 17 Mapple Street Male 18 Mapple Street

Figure 2 - Records of Students Table Now that we have 10 records, let's now add them to the Students table using SQL commands. 1> INSERT INTO Students (FirstName, LastName, Gender, Age, Address) VALUES 2> ('Edward', 'Lyons', 'Male', 17, 'Spencer Street'), 3> ('Jimmie', 'Vargas', 'Male', 18, 'Blue Bay Avenue'), 4> ('Monica', 'Ward', 'Female', 16, 'Mapple Street'), 5> ('Joann', 'Jordan', 'Female', 17, 'Spencer Street'), 6> ('Cheryl', 'Swanson', 'Female', 17, 'Wacky Street'), 7> ('Clara', 'Webb', 'Female', 18, 'Spooner Street'), 8> ('Zack', 'Norris', 'Male', 19, 'Blue Bay Avenue'), 9> ('Randall', 'May', 'Male', 18, 'Golden Street'), 10> ('Jessica', 'Cole', 'Female', 17, 'Mapple Street'), 11> ('Oscar', 'Manning', 'Male', 18, 'Mapple Street') 12> GO

We used a modified version of INSERT INTO Statement which allows inserting of multiple records at once. Each record is enclosed with parentheses and the records are separated with commas. After executing these SQL commands, your Students table should now be filled with 10 records. If everything went fine, a message will show up telling the number of rows affected. You can now skip the following section and proceed to the next lesson.

Querying Records With sqlcmd Utility

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

To perform a simple query in the sqlcmd Utility, you can use a simple SELECT statement. 1> SELECT FirstName, LastName FROM Students 2> GO FirstName LastName ------------------------- ------------------------Edward Lyons Jimmie

Vargas

Monica

Ward

Joann

Jordan

Cheryl

Swanson

Clara

Webb

Zack

Norris

Randall

May

Jessica

Cole

Oscar

Manning

(10 rows affected) 1>

Connecting to a Server Using SQL Server Management Studio In this part of the lesson we will do the exact same thing done in the previous section using the SQL Server Management Studio. If you have already done the previous section, then you should skip this part. Using SQL Server Management Studio is easier and you won't have to make use of SQL commands. SQL Server Managament Studio offers tools that would be helpful to you. Open SQL Server Management Studio by going to Start > All Programs > Microsoft SQL Server 2008 or Microsoft SQL Server 2008 R2. Once executed wait for the program to initialize some settings.

After that, the splash screen will show up while the program is loading.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You will then be prompted to choose the server name, the type of the authentication, and the login and password details. Leave the Server type as is. If you followed the tutorial on how to install Microsof SQL Server 2008 Express, note that we specified a name for the server instance. We used SQLEXPRESS as the name of the instance. This is important to know when connecting to a database. We will be using that name in the Server name field. Note that it is preceded by a dot and backslash which simply means the SQLEXPRESS server instance located in your own machine. You can change the dot to, for example, an ip address of a remote server where the server instance is located. You can choose Windows Authentication as the Authentication to use the credentials of your windows account. You may need to be logged in as the administrator of your computer. Choosing SQL Server Authentication allows you to log in using a SQL Server account. We can log in using the sa account, in which the password is what we have indicated when we installed Microsoft SQL Server. The Remember password checkbox remembers your password so you wont have to type it again when you open SQL Server 2008. Click Connect to connect to SQLEXPRESS server.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You are now connected to the SQLEXPRESS server.

Creating a Database with SQL Server Management Studio To the left of the interface is the Object Explorer which contains pretty much everything inside the server such as databases, tables, stored procedures, users, and many more. You can open up the Database folder to show databases that are already installed in your server. (You may not see any databases yet if this is your first time creating a database). To create a database, right click the Database folder and choose New Database.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The New Database Window will show up.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

We will be creating a database named University which will contain a table with records of students. Type the name of the database which is University in the Database name field. You can leave the owner to default. The Database files section allows you to customize the location where the database files (the files that contain the actual database) will be located in your disk. You can also leave it to default as you will need enough permissions to change the location of the database files. Two database files will be created, a .mdf file which contains the database itself, and a .ldf file which contains logging information and transactions made to the database. Also make sure to change the Initial sizes to 3 MB and 2MB respectively so the files can acccomodate the contents of the database. Press OK to create the database. Your created database should now appear inside the Database node of the Object Explorer.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Creating a Table in SQL Server Management Studio Creating a table is as simple as creating a database. In the Database node, find your created University database and expand it. Find the tables node and right click. Choose the New Table option.

The SQL Server's Table Designer will show up (Center) together with the Properties Window(Right) and the Column Properties Window Bottom.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can type the columns and their corresponding type in the Table Designer. The Properties window allows you to change certain properties of the table. The Column Properties window allows you to change certain properties of a column. In the Table Designer, type the following fields and their corresponding datatype.

Allow Nulls simply means that a column can be left blank for a single record. A good practice when designing tables is to uncheck this for a column that should always be required to have values. But for now, we are more concerned on creating a sample table that we can use in the following lessons. We should now set the primary key. The StudentID is the best candidate for a primary key and no two records should have the same StudentID. Select a particular column by clicking the blank

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

square to the left of the column's name then find in the toolbar the key icon which sets the selected column as the primary key.

The StudentID column will now have a key icon to its left to indicate that it is now the primary key. Also note that the its Allow Nulls check box was unchecked because primary keys should always have values.

We can also create the StudentID as the identity column. To do that, select the StudentID column and go to the Properties window. Find IdentityColumn and choose StudentID.

Save the table by pressing Ctrl + S. You will then be prompted for the name of the table. Name it Students and press OK to create our table with the name Students inside the University database.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You created table will appear in the Object Explorer inside the Tables node of the University database.

Adding Records to a Table Using SQL Server Management Studio We will now add some records in the Students ttable that we created. To add records, right click the Student table in the Object Explorer and choose Edit Top 200 Rows.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

A new window will show up that allows you to add records simply by typing each value to each field. The records that we will add is shown in Figure 2. Type each column data for every row. Note that StudentID is an identity column so you wont be able to type on it as SQL Server will auto generate a value for it.

Viewing Records in SQL Server Management Studio To View the records you create using SQL Server Management Studio, you can use the New Query command located in the toolbar.

The SQL Editor will show up. Type the following command. SELECT FirstName, LastName FROM Students;

If you read the first section of this tutorial, note that we used semicolon instead of the word GO. To Execute the SQL command, click the Execute button in the toolbar (The one with red exclamation point).

The query will then be executed and the results will be presented to you.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Close SQL Server Managment Studio. We are now ready to create an application that will connect to the University database, and query or modify the contents of the Students table.

Connecting to a Database with Visual Studio Tools Before we delve into the data-driven world of ADO.NET, let's first take a look at some tools available in the Visual Studio products. The following example shows you one way of connecting to a database without writing any code.

Creating a Connection to a Database Open Visual C# Express and create a new Windows Forms Application. Name the project as DatabaseConnection. In Visual Studio, the Database Explorer is called Server Explorer. It is opened by default in Visual C# Express located in the left as a tab.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

If you can't find the Database Explorer, go to View > Other Windows > Database Explorer to open it up. Click the Connect to Database icon in the Database/Server Explorer.

Clicking it shows up the Add Connection Window.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Be sure that the Data source uses Microsoft SQL Server Database File. If not, you can click the Change button and choose the appropriate data source. We also need to provide the file name of the database file that was created when we create our database. Click Browse to show up the open dialog. By default, the database files of SQL Server Express is located in C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data. Paste this path in the url bar of the Open dialog to immediately go to that directory. Find the University.mdf file and select it. Click Open. If an error shows up tellng that file is used by another program. Open up the Services program by clicking Start and typing the word services in the search box. Find the SQL Server (SQLEXPRESS) service and right click on it. Choose Restart to restart the service.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

After it is restarted, we can now go back to choosing the University.mdf file. After pressing open, click the Test Connection button in the Add Connection Window to test if our application can successfully connect to the database. If nothing is wrong, then a success message will show up.

Press OK to close the message. You can also choose the Authentication mode to be used. You can ues Windows Authentication or SQL Server Authentication. You must provide the username and password if you are to use SQL Server Authentication mode. Press OK to close the Add Connection Window and add the database file to the Database Explorer window.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Database Explorer allows you to see the contents of a database. If you expand a database file such as the University.mdf, you can see parts of it such as its tables and stored procedures. Expanding the Tables node shows our Students table and expanding the table shows its columns.

Creating a DataSet A DataSet can be considered as a mini database located in the computer's memory. It's main purpose is to obtain the data received from the database and store it in different tables just like how a database stores its records. The next step is to create a DataSet that will contain the contents the database that we have connected to. We will be using the Data Sources Window. If you can't see it, then go to Data > Show Data Sources. It will be located to the left of the IDE by default.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Click the Add New Data Source button to open up the Data Source Configuration Wizard.

Choose Database and click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Choose Dataset then click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

In the combo box, be sure to select University.mdf that we have connected using the Database Explorer. Click Next.

You will then be prompted that the database file needs to be coppied to the project's directory. Clicking yes will copy it to the project's directory. You can confirm that the database has been coppied by looking at the Solution Explorer and finding University.mdf.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

This window simply saves the connection string used to connect to the University database. Connection strings will be discussed in a later lesson. For now, you can leave the defaults and click Next.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Wait for the Wizard to load the contents of the database. You will then be asked which parts of the database you want to be included in the DataSet. Since we will only be needing the tables, simply check the Tables. The DataSet name specifies the name of the DataSet to be created. Click finish to create the DataSet.

You can now see the created DataSet in the Data Sources Window. Expanding it shows the tables contained in the data set. Expanding a table shows its fields or columns. Visual Studio also generated 4 files grouped as one which is used to created the DataSet. You can see them in the

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Solution Explorer. They contain all the codes that creates our DataSet. You don't have to look at them for now.

Showing Table Data Via Drag and Drop Now is the most exciting part. With our DataSet available in the Data Sources Window, we can simply drag a table to the form. You can also drag each column to a form but for now, we will drag a whole table to the form.

After dragging the table into the form, Visual Studio will automatically create a DataGridView control. The DataGridView allows you to view different kinds of data that can be represented in a table. An example is a database table or a multidimensional array of values. You can see that each column of the Students table was automatically placed in the DataGridView (try to resize the form and the DataGridView to see all the columns). You can also use the Dock property of the DataGridView and set it to Fill so the DataGridView will take up all the space of the form's client area. You will a toolbar on the top of the form. It is called the BindingNavigator control and Visual Studio also created this to allow you to move through records, update a record, delete an old record, and add a new record. If you also look at the component try below, more components have been automatically created for you by Visual Studio. We won't be discussing each of them for now because there are lot's of concepts to learn first. But if you are to create everything manually, then it can take us a lot of time to create what we have accomplished in this lesson. Run the application and you will see that all the records are displayed in the DataGridView. You can use the BindingSourceNavigator control to modify the contents of the database.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

You can use the navigation buttons to move from 1 record to another. The plus icon allows you to add new records. Don't worry if the StudentID that will be assigned for the new record is a negative number, it will be fixed by clicking the Save button which should be done to save the changes to the database. You can modify each field of a record by double clicking it. You can also delete a selected record by clicking the red X icon in the BindingNavigator control. Again, press the Save button after you have made a change to send the changes to the database. Note that running your program copies the database from the root project folder to the Release or Debug folder so everytime you run your program, you will be working with a fresh copy of the database. It means any modification to the database you make will be overwritten and discarded the next time you run your application. This is good when you are just developing the application. If you don't want this behavior, select the database file (University.mdf) in the Solution Explorer and in the find the Copy To Output Directory option in the Properties Window. Change its value to Copy if newer. The database file in the project's root directory will now only be coppied if it a newer version of the one that already exists in the output directory.

Connection Strings A connection string is a series of name/value pairs seperated by semicolon that indicate the settings for connecting to a database. Such settings include, the location of the database, authentication, security, and the name of the database to connect to. Connection strings for different data sources are not exactly the same. For example, OLE DB and ODBC requires an OLE DB and ODBC driver to be specified in their connection strings. The Connection classes of the data providers provides a ConnectionString property that you can use to specify the connection string for connecting to a database. Here is an example of a connection string for connecting to a SQL Server Expres data source:

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Data Source=.\SQLEXPRESS;Initial Catalog=University; Integrated Security=SSPI;

Figure 1 - A connection string example For a list of connection strings for different providers, you can go to the following site: http://connectionstrings.com The following table are the basic connection string parameters that you can use when building your connection string. Note that not all parameters are the same for every data source. Parameter

Description Used only if you want to connect to an attachable database file (for AttachDBFileName / Initial example, an .mdf file that isn't registered with the database File Name system). Full version of SQL Server doesn't support this. The length of time (in seconds) to wait for a connection to the Connect Timeout / server before terminating the attempt and generating an error. Connection Timeout Defaults to 15 seconds, and 0 seconds represents an infinite wait. ; Data Source / Server / The server name or network address of the database product to Address / Addr / Network connect to. Use localhost for the current computer. Address Initial Catalog / Database The database the the connection will initially use. Defaults to false. When set to true or SSPI, the .NET provider Integrated Security / attempts to connect to the data source using Windows integrated Trusted_Connection security. When set to false (the default), security-sensitive information such as the password is removed from the ConnectionString property as Persist Security Info soon as the connection is opened. Thus, you can't retrieve this information in your code. User ID The database account user ID. Password/Pwd The password corresponding to the User ID. Figure 2 - Connection String Parameters The example that we will show here are connection strings for connecting to an SQL Server data source. You can proceed to the website using the link above if you are finding the connection strings for other data sources such as Access. When building connection strings, you need to specify the data source or the server to be used. This can be done using the Data Source or the Server parameters. The connection string shown below is used for connecting to an SQL Express data source. Data Source=.\SQLEXPRESS;Initial Catalog=University;Integrated Security=SSPI;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

As specified by the Data Source parameter, ".\SQLEXPRESS", we are connecting to a server instance named SQLEXPRESS that lies within the current computer(localhost). Alternatively, you can use the word localhost instead so this is equivalent: "localhost\SQLEXPRESS". You can also specify the server or the computer name as the data source followed by the server instance. For example, suppose that the server we are connecting to is named MyServer and we want to connect to the SQLEXPRESS server instance, then the following connection string can be used. Data Source=MyServer\SQLEXPRESS;Initial Catalog=University; Integrated Security=SSPI;

You can also use the Server parameter instead of the Data Source which does the same thing. "Server=.\SQLEXPRESS;Initial Catalog=University; Integrated Security=SSPI"

We also need to specify the initial database to be used. The Initial Catalog or Database parameter indicates the initial database to use. You can change the database during runtime by calling the DbConnection.ChangeDatabase method or executing the SQL command "USE DATABASE " where is the name of the database that will replace the current database. Later lessons will show how to execute non-query SQL commands such as CREATE, UPDATE, and DELETE. Alternatively, you can use the Database parameter instead. Data Source=.\SQLEXPRESS;Database=University;Integrated Security=SSPI;

The connection string also requires authentication and security information. Integrated Security was set to SSPI (Security Support Provider Interface) signifying the we will be using the credentials of the current windows user. Data Source=.\SQLEXPRESS;Initial Catalog=University; Integrated Security=SSPI;

Alternatively, you can use the Trusted_Connection parameter instead and set it to True. Data Source=.\SQLEXPRESS;Initial Catalog=University; Trusted_Connection=True;

You can change this to a specific database user by replacing Integrated Security with the User Id and Password parameters. Data Source=.\SQLEXPRESS;Initial Catalog=University; User Id=database_user;Password=the_password;

When using Sql Server Express, we can also attach a database file on a local SQL server instance. We can use the AttachDbFilename to do just that. Data Source=.\SQLEXPRESS;AttachDbFileName=C:\Data\University.mdf; Database=University; Trusted_Connection=True;

We specified the path of the database file that we will use. If a Data Directory is defined, then you can use the |DataDirectory| instead.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|University.mdf; Database=University; Trusted_Connection=True;

ConnectionStringBuilder .NET also provides the ConnectionStringBuilder class for each of the data providers. ConnectionStringBuilder classes inherit from the DbConnectionStringBuilder base class. The following shows the different flavors of the ConnectionStringBuilder class. Provider ConnectionStringBuilder Class SQL Server SqlConnectionStringBuilder OLE DB OleDbConnectionStringBuilder ODBC OdbcConnectionStringBuilder Figure 3 - ConnectionStringBuilder Classes We will use SQL Server provider as our example. We can use the SqlConnectionStringBuilder class to create SQL Server connection strings. SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); builder.DataSource = @".\SQLEXPRESS"; builder.IntegratedSecurity = true; builder.InitialCatalog = "Northwind";

ConnectionStringBuilder contains properties which corresponds to the different parameters of a connection string. Each flavor of the ConnectionStringBuilder has different sets of properties because connection strings for different data sources are different. You can then access the connection string built by the ConnectionStringBuilder using the ConnectionString property. string connectionString = builder.ConnectionString;

There are more advanced parameters that you can use when building connection strings. Only the basic ones were introduced here to give you an essential knowledge for building connection strings.

Data Providers A data provider is a set of classes the manages and handles the connection to a data source such as SQL Server. The .NET Framework provides you with different data providers not just for SQL Server. For example, you can use the OLE DB and ODBC data providers to connect to other data sources such as Microsoft Access, MySql or even Oracle. The following are some of the data providers provided by .NET. There are currently three data providers supported by .NET. Provider COMPILED BY:

Description Bsc ABDULRAHIM ALI ATHUMAN

Provider Sql Server OLE DB Provider ODBC Provider

Description Provides access to a SQL Server database. Provides access to any data source that has an OLE DB driver such as MySQL, Provides access to any data source that has an ODBC driver.

Please note that another provider, Oracle Provider, has been considered deprecated since Microsoft recommends the use of ODP.NET instead. More data providers are offered by third party companies. Each data provider provides different classes that you can use to access your database. For example, the data provider for SQL Server consists of classes such as SqlConnection, SqlCommand, SqlDataReader, and SqlDataAdapter. The data provider for OLE DB consists of classes such as OleDbConnection, OleDbCommand, OleDbDataReader, and OleDbDataAdapter. The classes for the different providers inherit from a common set of classes and implement a common set of interfaces to provide consistent functionality regardless of the provider. Data Provider Sql Server OLE DB ODBC Components Connection SqlConnection OleDbConnection OdbcConnection Command SqlCommand OleDbCommand OdbcConnection DataReader SqlDataReader OleDbDataReader OdbcDataReader DataAdapter SqlDataAdapter OleDbDataAdapter OleDbDataAdapter Each data provider is located in its own namespace. For example, the Sql Provider is found inside System.Data.SqlClient and the OLE DB provider is found inside System.Data.OleDb. Data Provider Namespace Sql Server System.Data.SqlClient OLE DB System.Data.OleDb ODBC System.Data.Odbc The classes inside these namespaces implements a common interface. Consider the SqlConnection and OleDbConnection for example. They both implement the interface IDbConnection. If you look at this interface, you will see the common properties and methods of the Connection classes for all data providers. Note that the following lessons are mostly concepts and presents little code examples. This is OK as we will discuss how to use them in a working application after we have tackled this classes. You don't have to memorize each of them. In fact, you can skip the section and proceed to creating an ADO.NET application. You can then go back here whenever these classes are encountered on those lessons.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The Connection Class Each data provider in ADO.NET contains a Connection class that inherits from the System.Data.Common.DbConnection class. The DbConnection serves as the base class for all the Connection classes of different data providers. The following are the Connection classes for each data provider. Data Provider Connection Class SQL Server SqlConnection OLE DB OleDbConnection ODBC OdbcConnection Figure 1 - Connection Classes The DbConnection class implements the IDbConnection interface which contains methods and properties that is used to define a connection and to open a connection to a data source. Openning a connection consumes resources of the computer so you need to close it as soon as possible. For you to open a connection, you must specify a Connection String to indicate the location, type and other configurations for connecting to a database source. The following are the methods and properties of the IDbConnection interface that are common to all Connection classes. Property ConnectionString

Description Specifies the connection string to be used by the connection. Specifies the time to wait for the connection to be established before ConnectionTimeout declaring that the connection has timed out. Database Specifies the database that the connection is currently working on. State Specifies the current state of the connection. Figure 2 - IDbConnection Properties Method Description BeginTransaction Begins a database transaction. ChangeDatabase Changes the database the connection is currenly working on. Close Closes the connection. CreateCommand Creates and returns a command object associated with the connection. Open Opens the connection. Figure 3 - IDbConnection Methods

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Note that each Connection class of every data provider can have more properties and methods listed below which are unique to them. Let's use the SQL Server as the data provider for the following examples. It means that we will be using the SqlConnection class which is the Connection class of SQL Server data provider. To create a Connection object, simply use its parameterless constructor. SqlConnection connection = new SqlConnection();

We need to specify the proper connection string for the connection. To assign a connection string to the Connection object, you can use the ConnectionString property. connection.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=University;" + "Integrated Security=SSPI";

Alternatively, you can use the overloaded constructor of the SqlConnection class when creating an instance of it. SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;" + "Initial Catalog=University;Integrated Security=SSPI");

The connection string above specifies a connection to an SQL Server database using the University as the initial database with Window Authentication. The ConnectionString property is set only when the connection is closed. The Connection class offers a number of properties that access the different components of the connection string. The Database property specifies the database to use. The initial database is indicated by the Initial Catalog parameter of the ConnectionString. To change the database to use, you can call the ChangeDatabase method as shown in the following code. connection.ChangeDatabase("AnotherDatabase");

The code changes our database from University(specified in the connection string) to AnotherDatabase, provided that the AnotherDatabase database exists. The ConnectionTimeout property gets the value of the Connection Timeout parameter of the connection string. If it is not specified, it has a default value of 15. The Connection Timeout specifies how long the connection has to wait before it throws an exception indicating that a connection has timed out. To open a connection, we use the Open method. Be sure you have set the details needed in the connection string before calling this method. After you have used the database, you can use the Close method. Note that you can use the using keyword to automatically close the connection. This is shown below. using (SqlConnection connection = new SqlConnection()) {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

// some code.... connection.Open(); // some code.... }

We put the declaration and initialization between the parentheses of the using statement. This means the the object created between these parentheses is only usable inside the block of the using statement. Once the closing blocked is reach, the Connection object is disposed automatically closing the connection. If you are using the Close method, be sure to always put it in the finally block like this. try { connection.Open(); } catch(SqlException) { } finally { connection.Close(); }

This is because, if you put it inside the try block, and an exception was thrown, then the statement that calls the Close method might not be reached leaving the connection open. If it is in the finally block, then the Close method will always be called. You can use the State property to know the current state of a connection, whether it is close or open. The State property accepts a value from the System.Data.ConnectionStateEnumeration. The following are the values of the ConnectionState enumeration. Value Description Broken States that the connection is broken. Closed States that the conneciton is closed. Connecting States that the connection is currently connecting to a data source. Executing States that the connection is executing a command. Fetching States that the connection is retrieving data. Open States that the connection is open. Figure 4 - System.Data.ConnectionState Enumeration Values The Connection class offers two events that you can use. The first one is the InfoMessage event which is used to get specific information messages. The StateChange event is triggered when the connection state is changed. static void con_StateChange(object sender, System.Data.StateChangeEventArgs e) { Console.WriteLine("State has been changed from {0} to {1}.",

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

e.OriginalState.ToString(), e.CurrentState.ToString()); } static void Main() { SqlConnection con = new SqlConnection(); con.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=University;" + "Integrated Security=SSPI"; con.StateChange += new System.Data.StateChangeEventHandler(con_StateChange); con.Open(); // Opens a connection con.Close(); // Closes a connection } State has been changed from Closed to Open. State has been changed from Open to Closed.

When we called the Open() method, the connection's state was changed from Close to Open, triggering the event handler that is attached to the StateChange event. The event handler prints a message that shows the OriginalState and CurrentState. When we called the Close() method, the connection state was changed from Open to Closed also trigerring the StateChange event.

The Command Class Each data provider has their Command class which is use to execute SQL commands or stored procedures to the database. Each Command class inherits from the System.Data.Common.DbCommand base class. The following are the different flavors of the Command class for each data provider. Data Provider Command Class Sql Server SqlCommand OLE DB OleDbCommand ODBC OdbcCommand Figure 1 - Command Classes DbCommand implements the IDbCommand interface which exposes some properties and methods as shown in the following tables. Property CommandText

Description Specifies the SQL command or stored procedure or a name of a table. Specifies the time required to wait for the completion of a command before it CommandTimeout throws an exception. The default is 30 seconds. Accepts a value from the System.Data.CommandType enumeration that will determine the type of command specified in the CommandText property. It CommandType has 3 values, Text, for accepting SQL commands, StoredProcedure for stored procedures, and TableDirect to get all the rows and columns of one or

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Property

Connection Parameters

Description multiple tables. Note that by default, Text will be used. Specifies the connection that the command is associated to. The Command class must be hooked to an open connection which is the connection where the command is to be executed. A collection of Parameter defined in the CommandText.

FIgure 2 - IDbCommand Properties Property Cancel

Description Tries to cancel the command being executed. Creates a new Parameter object that can be added to Command.Parameters CreateParameter collection. Executes the command and returns a forward-only read-only cursor in the ExecuteReader form of a DataReader. Executes the command and returns the number of rows that were affected. ExecuteNonQuery Often used with record UPDATE, DELETE, or INSERT statements. Executes the command, and retrieves a single value. Used with aggregate ExecuteScalar functions and in cases where you want to return the first column of the first row of a result set. Figure 3 - IDbCommand Methods We wll use the SQL Server provider's SqlCommand class for the following examples. To create a Command object, you can simply use it's parameterless constructor. SqlCommand command = new SqlCommand();

A command is useless without specifying the CommandText which contains an SQL statement that the command will execute. command.CommandText = "SELECT * FROM Students";

Alternatively, you can immediately specify the command text when creating the Command object using an overloaded constructor of SqlCommand. SqlCommand command = new SqlCommand("SELECT * FROM Students");

Another required thing that the Command object should have is the Connection object where the command will be executed to. When you have created a Connection(for example, an SqlConnection object), then you can assign its instance to the Connection property of the IDbCommand. SqlConnection connection = new SqlConnection(); SqlCommand command = new SqlCommand();

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

command.Connection = connection;

An overloaded version of the constructor allows you to specify the command text and the connection to be used by the command. SqlCommand command = new SqlCommand("SELECT * FROM Students", connection);

The DbConnection class also offers a CreateCommand() method which returns a DbCommand with the connection already hooked to it. You can then use the CommandText property to specify the command. SqlCommand command = connection.CreateCommand(); command.CommandText = "SELECT * FROM Students";

To execute commands, you first need an open connection. For reading the contents of a database, you can use the ExecuteReader() method which reaturns a DataReader object that can be used to step through each row of a database table. For updating, inserting, deleting, and any non-query commands, you can use the ExecuteNonQuery() method. These methods will be seen in action in a later lesson. Other properties and methods of the Command classes are reserved for later lessons. But for now, the ones introduced here are enough to execute basic SQL statements.

The DataReader Class A DataReader object allows forward-only, read-only access to a database. Using DataReader is the connected way of accessing data and an open connection must be available first. Each provider has its own version of DataReader which inherits to the System.Data.Common.DbDataReader base class. Provider DataReader class SQL Server SqlDataReader OLE DB OleDbDataReader ODBC OdbcDataReader Figure 1 - DataReader Classes The DbDataReader class contains properties and methods used for reading a row in a database table. Some of this are presented in the following tables. Property FieldCount HasRows IsClosed

COMPILED BY:

Description Specifies the number of columns of the current row or record. Specifies whether the current row has at least 1 row. Specifies whether the DbDataReader is closed.

Bsc ABDULRAHIM ALI ATHUMAN

Property Description RecordsAffected Specifies the number of rows that has been updated, inserted, or deleted. Figure 2 - DbDataReader Properties Method Description GetBoolean Gets the value of a column as a boolean value. GetChar Gets the value of a column as a char value. GetDataTypeName Gets the name of the data type of the current column. GetDateTime Gets the value of the column as a DateTime object. GetDecimal Gets the value of the column as a decimal value. GetDouble Gets the value of the column as a double value. GetFieldType Gets the field type of the specified column. GetInt32 Gets the value of the column as a int value. GetName Gets the name of the column. GetOrdinal Gets the column ordinal with the specified column name. GetString Gets the value of the column as a string value. GetValue Gets the value of a column as an object. GetValues Gets all the column of a row as an array of objects. Advances the reader to the next result when reading the NextResult results of a batch of statements. Read Advances the reader to the next record. Figure 3 - DbDataReader Methods The DataReader only loads a single row in the memory at a time to ensure the minimum use of memory. DataReader can only be used when a connection is open, so you need to open a conenction first and as soon as you are over using it, then you must close the connection. A corresponding command assigned with an SQL SELECT statement should call the ExecuteReader() method to create an instance of DbDataReader object. Again, we will use SQL Server provider for the following examples. (Suppose that a connection was already declared). SqlCommand command = new SqlCommand("SELECT * FROM Students", connection); SqlDataReader reader; connection.Open(); reader = command.ExecuteReader();

You can see that we first need an Open connection before using the ExecuteReader() method. We did this using the DbConnection.Open() method. An overloaded version of the ExecuteReader() method also exists that accepts a value from the System.Data.CommandBehavior enumeration. Here are some of its values you can use.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Value CloseConnection Default SingleResult SingleRow

Description Immediately closes the connection when the Close method of the DataReader is called. The default behavior of the DataReader. The query returns a single result set. The query is expected to return only a single row.

Figure 4 - System.Data.CommandBehavior Enumeration Values For example, if you want the reader to only read a single row, then you should past the SingleRow value to the ExecutReader() method. reader = command.ExecuteReader(CommandBehavior.SingleRow);

You can also combine command behaviors using the bitwise OR operator. reader = command.ExecuteReader(CommandBehavior.SingleRow | CommandBehavior.CloseConnection);

Once the ExecuteReader() was executed and an instance of DbDataReader was placed in a variable, we can now iterate through each record of the result set that was returned by by SELECT statement. The following shows you how to obtain the value of each field of every row. while (reader.Read()) { MessageBox.Show(reader["FirstName"].ToString()); }

We used a for loop and inside its condition, we used the Read() method of the DataReader to read the first row of the result set that was returned by the query. If a row was successfully read, the method will return true and continue the loop. Once that method is executed, we can used an indexer for the DataReader object and pass the name of the column. This will return the result as an object so we need to convert it first to its proper data type. After the body of the loop is executed, the Read() method is executed once again to read the next row. If there the row previously read is the last row and no other rows left to be read, then the Read() method will return false and stop the loop. Alternatively, you can use the Get methods of the DataReader which accepts the column index of the value to be retrieved. For example, suppose we want to retrieve the StudentId which is a number, then you can use the following code. int studentID = reader.GetInt32(0);

This will return the value of the first column (index 0) as a value of type int. After using the DataReader, you need to close the DataReader and the Connection to release the resources that was used and to make the connection availabe.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

reader.Close(); connection.Close();

We will use the DataReader classes to read the contents of a database in a connected fashion and it will be demonstrated in a later lesson.

The DataAdapter Class A DataAdapter can be considered as a bridge between the actual data source to your application. It is commonly used together with a DataSet. Using DataAdapter and DataSet is the disconnected way of retrieving data from the data source. It means, you don't need an open connection for them to work. A DataAdapter allows you to fill a DataSet with values from the data source, or execute different commands to the data source.A DataAdapter class inherits from the System.Data.Common.DbDataAdapter base class. Each data provider has its own version of DataAdapter. Provider DataAdapter Class SQL Server SqlDataAdapter OLE DB OleDbDataAdapter ODBC OdbcDataAdapter Figure 1 - DataAdapter Classes The DbDataAdapter class provides the following properties and methods. Property

Description Speicfies the Command object with the SQL command to be used for DeleteCommand deleting a record. FillCommandBehavior Specifies the behavior of the command used to fill the data adapter. Specifies the Command object with the SQL command yused for InsertCommand inserting a record. Specifies the Command object with the SQL command to be used for SelectCommand inserting a record. UpdateBatchSize Specifies the number of commands that can be executed as a batch. Specifies the Command object with the SQL command to be used for UpdateCommand inserting a record. Figure 2 - DbDataAdapter Properties Method AddToBatch ClearBatch ExecuteBatch COMPILED BY:

Description Adds a Command object to a batch that will be executed. Removes all the Command objects from the batch. Excutes the batch of commands. Bsc ABDULRAHIM ALI ATHUMAN

Method

Description Fill Executes the SelectCommand property and fills a DataSet that is provided. InitializeBatching Initialize the batching process. GetFillParameters Gets the paremeters of the SelectCommand property. TerminateBatching Terminates the batching process. Calls the corresponding INSERT, DELETE, or UPDATE command of this Update DataAdapter and updates the data source using the specified commands. Figure 3 - DbDataAdapter Methods We will use the SQL Server provider for the folowing examples. To create a DataAdapter, you can use its parameterless constructor. SqlDataAdapter adapter = new SqlDataAdapter();

The DataAdapter is the one that actually executes the commands to data source. It has a SelectCommand property which accepts a DbCommand object that specifies the SELECT statement used to retrieved data from the data source. The following shows you an example of assigning a SelectCommand. SqlCommand selectCommand = new SqlCommand("SELECT * FROM Students", connection); SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand = selectCommand;

To execute the command specified by the SelectCommand property, we can use the Fill() method of the DbDataAdapter class. The Fill() method requires an instance of the DataSet or DataTable classes. The following shows an example of filling a DataTable instance with values retrieved from the database. DataTable myTable = new DataTable("TableName"); adapter.Fill(myTable);

This will execute the command indicated in the SelectCommand property and the results of the query will be stored in the DataTable. The following is another form of the Fill command which accepts a DataSet and the name of the DataTable to be created. DataSet myDataSet = new DataSet(); adapter.Fill(myDataSet, "TableName");

After execution of the above command, a new DataTable with the name TableName will be added to the Tables property oft the DataSet. You can then access the data using the Rows property of the DataTable.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The DbDataAdapter also allows you to specify commands for its UpdateCommand, InsertCommand, and DeleteCommand properties. Note that these commands will be autogenerated by a CommandBuilder as we will see in a separate lesson. You can then use the Update() method of the DbDataAdapter which executes these commands depending on the modification to the DataSet. You will see how to update, insert, and delete records using the Update() method in an upcoming lesson.

The DataSet Class The System.Data.DataSet class holds data that are retrieved from the database. The DataSet class allows you to hold disconnected data. It means, you can work with the contents of the database while disconnected to the actual database. This is because, the contents that you will be working on already exists inside the DataSet. You can consider the DataSet class as a mini database management system inside the memory. The DataSet class has a Tables property which is a collection of System.Data.DataTable objects. A typical database can contain multiple tables. Just like a database, a DataSet can contain multiple tables as well. Records retrieved from the actual database are stored as a DataTable and added to the Tables property of the DataSet. The DataTable also has properties named Columns and Rows which are collections of DataColumn and DataRow respectively. This properties contain the individual columns and rows of the table from the database. The good thing about the DataTable and DataColumn is that, they can be assigned with names. This is done by using the TableName and ColumnName properties or using their constructors. Let's create a simple DataTable and add it to the a DataSet. Create a new Windows Forms Application and name it DataSetDemo. Add a DataGridView from the toolbar and set its Dock property to Fill.

Double click the title bar of the form to generate an event handler for the form's Load event. First, be sure to import the System.Data namespace. Use the following code for the Load even handler. 1 private void Form1_Load(object sender, EventArgs e)

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

2 { 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46}

//Initialize components DataSet personsDataSet = new DataSet(); DataTable personsTable = new DataTable("Persons"); DataColumn firstNameColumn = new DataColumn("FirstName"); DataColumn lastNameColumn = new DataColumn("LastName"); DataColumn ageColumn = new DataColumn("Age"); DataRow firstPerson; DataRow secondPerson; DataRow thirdPerson; //Construct the table's column personsTable.Columns.AddRange(new DataColumn[] { firstNameColumn, lastNameColumn, ageColumn }); //Create three rows/records firstPerson = personsTable.NewRow(); secondPerson = personsTable.NewRow(); thirdPerson = personsTable.NewRow(); //Assign values to rows firstPerson["FirstName"] = "Mark"; firstPerson["LastName"] = "Davidson"; firstPerson["Age"] = 18; secondPerson["FirstName"] = "John"; secondPerson["LastName"] = "Fredrich"; secondPerson["Age"] = 22; thirdPerson["FirstName"] = "Chelsey"; thirdPerson["LastName"] = "Bells"; thirdPerson["Age"] = 19; //Add the rows to the table personsTable.Rows.Add(firstPerson); personsTable.Rows.Add(secondPerson); personsTable.Rows.Add(thirdPerson); //Add the table to the DataSet personsDataSet.Tables.Add(personsTable); dataGridView1.DataSource = personsDataSet.Tables["Persons"];

Example 1 Lines 4-11 declares the different classes for creating a complete DataTable and DataSet. Notice the passed names inside the constructor for the DataTable and each DataColumn. This will make them easier to reference when we call them using the DataSet. Lines 14-17 adds the created DataColumn object to the Columns property of the DataTable. It is important that you do this first before specifying the rows. Lines 20-22 initializes each DataRow object using the DataTable.NewRow() method which returns a DataRow object that already has the proper

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

number of values it can have. Lines 25-35 assigns values to each field of the DataRow objects. Note that each field was accessed via indexers that accepts that name of the corresponding DataColumn. To complete the DataTable, lines 38-40 adds all the rows to the DataTable.Rows property. Finally, we added the DataTable object to the Tables property of the DataSet. To access the table that we have added, we can use an indexer for the Tables property and pass the name of the table. We assign the table to the DataSource property of the DataGridView so it will show the contents of the DataTable that we have created. Run the program and you will see the records of the table inside the DataGridView control.

Connecting to a Database Through Code The first example we encountered for connecting to databases involves Visual Studio tools that doesn't require you to type any code at all. We will now begin a series of lessons which concentrates on using the ADO.NET classes to type codes that connect to differet data sources. We will use Windows Forms Application project type to present the different examples of connecting to a data source. You should have also followed the lesson on creating a database and table where we created the database and table that we will need in the following lesson. What we will be covering in the next lessons is how to query (retrieve records), insert or add records, delete records, and update existing records. I will present two ways of doing this things, the connected way and the disconnected way. Although both does the same thing, they have their specific purposes and scenarios where you can use them. The connected approach is good if you want to execute commands quickly and you are working with a big sets of data. The disadvantage of it is that, you need to open the connection and no other connection can use it until you close it again. The disconnected approach is recommended if you are working with small chunks of data from the database. One big advantage of using it is that you don't need an open connection as the results are filled inside a DataSet. You can then do the modifications in the DataSet and submit the changes to the database later. If you have already tried out connecting to the database using the tools offered by Visual Studio, this time, you have to type every single code used to connect to the data source. Why do this if such tools already exists? This is because those tools generates hundreds of lines of code which is optimized and full of advanced stuffs you won't be needing for a simple data-driven application. The codes we will write will only contain several lines of code. As we progress we will modify the codees we will learn and apply them to more advance applications and techniques. Note again that we will be using the Microsoft SQL Server 2008 Express as our main data source and I am assuming that you have installed it correctly including the sample database and tables we have created.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Querying a Database: Connected Approach Querying is the process of retrieving data from a data source such as a database. We can do queries using the SELECT statement of the SQL. You will learn how to use this statement to query a table in a database using ADO.NET classes. We will present the connected approach of querying data from the data source. The following are the basic steps you should follow when querying results with an open connection. 1. Create A Connection 2. Create A Command 3. Create A DataReader 4. Specify connection string for the Connection 5. Specify Connection that will be used for the Command 6. Specify the CommandText that will be executed by the Command 7. Add values to command parameters (if any). 8. Open the Connection 9. Execute DataReader 10. Read every row from the result set 11. Close the Reader 12. Close the Connection With this steps, we can already query a table of data from the database. To demonstrate these steps, let's create a new Windows Forms Application and name it QueryingDatabaseConnected. Add a ListBox control to the form and name it studentsListBox.

Figure 1 Double click the title bar to generate an event handler for the form's Load event. Be sure to import the System.Data.SqlClient at the top. COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

using System.Data.SqlClient;

Use the following code for the Load event handler. private void Form1_Load(object sender, EventArgs e) 1 { 2 SqlConnection connection = new SqlConnection(); 3 SqlCommand command = new SqlCommand(); 4 SqlDataReader reader; 5 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial 7 Catalog=University;" 8 + "Integrated Security=SSPI"; 9 command.Connection = connection; 10 command.CommandText = "SELECT FirstName, LastName, Age FROM Students"; 11 12 connection.Open(); 13 reader = command.ExecuteReader(); 14 15 while (reader.Read()) 16 { 17 string firstName = reader["FirstName"].ToString(); 18 string lastName = reader["LastName"].ToString(); 19 int age = Convert.ToInt32(reader["Age"]); 20 21 studentsListBox.Items.Add(String.Format("{0} {1}, 22{2}",firstName,lastName,age)); 23 } 24 25 reader.Close(); 26 connection.Close(); }

Example 1 Line 3 creates a Connection object (Step 1). Line 4 creates a command object (Step 2). Line 5 declares a reader object (Step 3). Line 7 assigns the proper connection string for our connection (Step 4). The connection string uses the SQLEXPRESS server instance and the University database as the initial database. Line 9 assigns the Connection to be used by the Command object (Step 5). Line 10 specifies the SQL command for the Command object (Step 6). The command specifies that we get the FirstName, LastName, and Age of every record from the Students table. The SQL command assigned to the CommandText of the Command has no parameters so we can skip Step 7 which adds the required values to command parameters. We then open the connection in line 12 by usign the DbConnection.Open() method (Step 8). Line 13 creates a DbDataReader instance using the DbCommand.ExecuteReader() method and we assigned the returned DbDataReader object to a variable so we can use it later (Step 9). Lines 15 to 22 iterates each row of the result set returned by executing the SELECT statement of the Command (Step 10). We used the DbDataReader.Read() method to obtain the first row of the result set. If there is at least one row available, the Read() will return true and the loop will continue. We then assigned the values of each column to their specific variables(lines 17-19). We used the indexer for the DbDataReader object that accepts a string representing the name of the column. We then converted their results to proper data types. For example, we converted the content of COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

reader["Age"] to integer and stored it to an integer variable. Line 21 simply adds the retrieved data to the Items of the ListBox. After the first loop, the Read() method will execute again and obtain the next row in the result set. If no more records are found, then Read() will return false and exit the loop. After exiting the loop, we closed the DataReader in line 24 (Step 11) and also the Connection in line 25 (Step 12). Execute the program and you will see the following output.

Figure 2 By using a while loop in our code, the Read() method was executed until no more records are found. Each record was then added to the ListBox and presented to the user. You can simplify the code even more by taking advantage of the overloaded constructors of the DbConnection and DbCommand classes. For example, you can simple combine Step 1 and Step 4 by using the DbConnection's overloaded constructor that accepts the connection string. SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;" + "Initial Catalog=University;Integrated Security=SSPI");

You can combine Steps 2, 5, 6 by using the DbCommand's overloaded constructor that accepts the command text and the connection to be used. SqlCommand command = new SqlCommand( "SELECT FirstName, LastName, Age FROM Students", connection);

Another thing is that we can use the using statement when creating a connection. Consider the following modifications to the code in Example 1. 1 using (SqlConnection connection = new SqlConnection()) 2 { 3 SqlCommand command = new SqlCommand(); 4 SqlDataReader reader;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

5 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial 7 Catalog=University;" 8 + "Integrated Security=SSPI"; 9 command.Connection = connection; 10 command.CommandText = "SELECT FirstName, LastName, Age FROM Students"; 11 12 connection.Open(); 13 reader = command.ExecuteReader(); 14 15 while (reader.Read()) 16 { 17 string firstName = reader["FirstName"].ToString(); 18 string lastName = reader["LastName"].ToString(); 19 int age = Convert.ToInt32(reader["Age"]); 20 21 studentsListBox.Items.Add(String.Format("{0} {1}, {2}", 22 firstName, lastName, age)); 23 } 24 25 reader.Close(); }

Example 2 The whole connnection procces was enclosed inside the using block. On the first line of the using statement, we placed the declaration and initialization of the Connection object. This signifies the using block to immediately destroy the Connection the moment it exits the block. So if the execution reaches the closing brace of the using block, our Connection will be destroyed, and as a result, it will automatically be close. That's why, we can omit the call to DbCommand.Close() method. This technique is better because it ensures that the connection will be closed when you are finished using it. Note that the Connection object will no longer be accessable once the execution leaves the using block. Another good practice is enclosing the connection process into a try catch finally block. This ensures the program that it can handle any database errors or exceptions it can encounter during runtime. Suppose for example that the connection string is wrong or the connection has timed out, then exceptions will be thrown and you need to handle them. We can start adding the try block from the line where the DbConnection.Open() was called. 1 try 2 { 3 connection.Open(); 4 reader = command.ExecuteReader(); 5 6 while (reader.Read()) 7 { 8 string firstName = reader["FirstName"].ToString(); 9 string lastName = reader["LastName"].ToString(); 10 int age = Convert.ToInt32(reader["Age"]); 11 12 studentsListBox.Items.Add(String.Format("{0} {1}, {2}", 13 firstName, lastName, age));

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

14 } 15} 16catch (SqlException e) 17{ 18 MessageBox.Show(e.Message); 19} 20finally 21{ 22 reader.Close(); 23 connection.Close(); 24}

Example 3 From the moment of opening the connection, to accessing the contents of each row, exceptions can be thrown so we enclosed all of them in a try block. We used the SqlException class in the catch block (line 16) which is an SQL Server provider's version of DbException, to handle any database related errors. We then show the error message to the user using the Message property. We placed the codes that closes the DataReader and the Connection (lines 22-23) inside the finally block. We did this to ensure that this codes will always execute regardless of whether exceptions were found or not. If you used a using statement as shown earlier, then you wont have to write the code for closing the Connection. Try to get a habit of using exception handling when connecting and accessing a data source.

Querying a Database: Disconnected Approach We can query results from a database without keeping an open connection. This is through the help of the DataAdapter classes and the DataSet class. The DataAdapter executes commands to the database and fills the results returned by the query inside a table of the DataSet. You can then access every record using the Rows property of the DataTable or every values of its fields by specifying the name of the column. The following are the basic steps for querying and displaying a result set from a database using the disconnected approach. 1. Create a Connection 2. Create a Command 3. Create a DataAdapter 4. Create a DataSet 5. Specify connection string for the Connection 6. Specify Connection that will be used by the Command 7. Specify the CommandText that will be executed by the command 8. Add values to command parameters (if any) 9. Specify SelectCommand for the DataAdapter 10. Fill the DataSet using the DataAdapter 11. Display results Let's create a simple application to demonstrate these steps. We will create an application that shows the result returned by a query using the disconnected approach. Create a new Windows

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Forms Application and name it QueryingDatabaseDisconnected. Add a ListBox to the form and name it studentsListBox.

Figure 1 Double click the form to generate the event handler for the form's Load event. Be sure to import the System.Data namespace for the DataSet class, and the System.Data.SqlClient namespace for classes required for connecting to SQL Server. using System.Data; using System.Data.SqlClient;

After that, use the following code for the Load event handler. 1 private void Form1_Load(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 SqlDataAdapter adapter = new SqlDataAdapter(); 6 DataSet dataset = new DataSet(); 7 8 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 9 "Initial Catalog=University;Integrated Security=SSPI"; 10 command.Connection = connection; 11 command.CommandText = "SELECT FirstName, LastName, Age FROM Students"; 12 adapter.SelectCommand = command; 13 adapter.Fill(dataset, "Students"); 14 15 foreach (DataRow student in dataset.Tables["Students"].Rows) 16 { 17 studentsListBox.Items.Add(String.Format("{0} {1},{2}", 18 student["FirstName"], student["LastName"], student["Age"]));

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

19 20}

}

Example 1 Lines 3-6 creates the necessary objects as stated in Steps 1 to 4. We then assigned the connection string to the ConnectionString property of the Connection object (lines 8-9). Lines 10-11 assigns the Connection and CommandText to be used by the Command object. Since there is no command parameters specified in the command text, we can skip Step 8. Line 12 specifies the Command to be used as the SelectCommand by the DataAdapter. We passed the Command that we created which retrieves the FirstName, LastName, and Age of every student. Line 13 uses the Fill() method of the DataAdapter to execute the command. The first argument of the method is the DataSet to be filled and the second argument is the name of the table that will hold the result set. The Fill() method creates a DataTable with the specified name where the result set will be contained. Then that DataTable will be added to the Tables property of the DataSet. Lines 15 to 19 access each row in the DataTable using a foreach loop. As you can see, we used the Tables property of the DataSet and specified the name of the table using an indexer. We then used the Rows property of the returned DataTable which contains the collection of all DataRows of the result set. We assigned each row in a temporary variable student. Line 17 adds the value FirstName, LastName, and Age fields using indexers and specifying the name of the collumn. Execute the application and you will see all the students loaded in the ListBox.

Figure 2 Using the disconnected approach, we can also easily bind a DataTable into a DataGridView control. As an example, let's modify our previous application by deleting the ListBox control and replacing it with a DataGridView control with the name studentsDataGridView.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 3 Modify the code inside the form's Load event handler. private void Form1_Load(object sender, EventArgs e) { SqlConnection connection = new SqlConnection(); SqlCommand command = new SqlCommand(); SqlDataAdapter adapter = new SqlDataAdapter(); DataSet dataset = new DataSet(); connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + "Initial Catalog=University;Integrated Security=SSPI"; command.Connection = connection; command.CommandText = "SELECT FirstName, LastName, Age FROM Students"; adapter.SelectCommand = command; adapter.Fill(dataset, "Students"); studentsDataGridView.DataSource = dataset.Tables["Students"]; }

Example 2 We used the DataSource property of the DataGridView the specifies the source of data to be shown by the control. We specified it's value to be the DataTable that we have field by accessing the Tables property and providing the name we have specified in the indexer. Execute the program and see the results.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 4 We have seen how to query results using the disconnected approach using the DataAdapter and the DataSet classes.

Inserting Records: Connected Approach Inserting records is very easy to do using the ADO.NET's Command classes. We will discuss inserting of records using the connected approach. We will also take a look at using parameters. The following are the basic steps of inserting record. 1. 2. 3. 4. 5. 6. 7. 8. 9.

Create a Connection Create a Command Specify connection string to Connection Specify Connection that the Command will use Specify the INSERT Statement for the CommandText of the Command Add values to command parameters if any Open Connection Execute the command Close Connection

You can see that the steps are fewer compared to querying a data from a database. The following application uses the University database and allows you to insert new records to the Students table. Create a new Windows Forms Application and name it InsertingRecordsConnected. Add labels and text boxes for FirstName, LastName, Gender, Age, and Address fields. Name the textboxes firstNameTextBox, lastNameTextBox, genderTextBox, ageTextBox, and addressTextBox. Also add a button and name it addButton.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 1 Double click the button to generate an event handler for its Click event. Import the System.Data.SqlClient and use the following code for the handler. 1 private void button1_Click(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 7 "Initial Catalog=University;Integrated Security=SSPI"; 8 command.Connection = connection; 9 command.CommandText = "INSERT INTO Students " + 10 "(FirstName, LastName, Gender, Age, Address) VALUES " + 11 "(@FirstName, @LastName, @Gender, @Age, @Address)"; 12 13 command.Parameters.AddWithValue("@FirstName", firstNameTextBox.Text); 14 command.Parameters.AddWithValue("@LastName", lastNameTextBox.Text); 15 command.Parameters.AddWithValue("@Gender", genderTextBox.Text); 16 command.Parameters.AddWithValue("@Age", ageTextBox.Text); 17 command.Parameters.AddWithValue("@Address", addressTextBox.Text); 18 19 try 20 { 21 connection.Open(); 22 int result = command.ExecuteNonQuery(); 23 if (result > 0) 24 MessageBox.Show("Student successfully added!"); 25 else 26 MessageBox.Show("Failed to add student!"); 27 } 28 catch (SqlException ex) 29 {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

30 31 32 33 34 35 36}

MessageBox.Show("An error has occured!"); } finally { connection.Close(); }

Example 1 We only declared a Connection and a Command because they are sufficient to do our task for inserting records. We also assign an INSERT statement as the CommandText for our command (lines 9-11). As you can see, the command has several command parameters which starts with @ symbol. Also notice that we didn't specify the StudentID in the list of parameters becuase it is an identity field and will automatically be assigned with a value. Lines 13-17 adds values to each parameter using the AddWithValue() method of the DbCommand's Parameters property. This method accepts the command parameter name, and the actual value that will replace it. For example, we are going to change the @FirstName parameter with whatever the text of firstNameTextBox. Inside a try block, we open the connection and execute the command using the DbCommand.ExecuteNonQuery() method (line 22). This method is used to execute nonquery SQL statements such as INSERT, DELETE, UPDATE, and CREATE which are statements that doesn't return result sets. The method returns an integer value which represents the number of rows affected. Since we insert a record, we are expecting the value 1 to be returned. We placed the returned value in a variable. Using an if statement in line 23, we tested if the rows affected is not 0 to confirm that the the row was successfully updated. The catch block catches all the SqlException that will be thrown inside the try block. We simply write a code that will show an error message when a database-related error occured such as wrong connection string. The finally block contains the code to close the connection. Execute our program and add text values that will be inserted to the Students table.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 2 Click the add button to insert the record. If nothing is wrong, then a success message will show up.

Figure 3 The next lesson will take a look at adding records using the disconnected approach.

Inserting Records: Disconnected Approach Inserting records using the disconnected approach is a little different compared to doing it using the connected approach. We need to use the DataAdapter and the DataSet classes. When modifying records using the disconnected approach, what we modify is the contents of the DataTable, then after the modification, we submit the changes to the database. So if we want to insert a new records, then we add a DataRow in the Rows property of the DataTable. After that, we invoke the Update() method which will submit the inserted row to the actual database table. The INSERT command used for it is generated by a CommandBuilder object which is available

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

for each data provider. For example, for SQL provider, you can use the SqlCommandBuilder class. The following are the basic steps for inserting a record using the disconnected approach. 1. Create a Connection 2. Create a Command 3. Create a DataAdapter 4. Create a CommandBuilder and associate it to the DataAdapter 5. Create a DataSet 6. Specify connection string for the connection 7. Specify Connection to be used by the Command 8. Specify CommandText for the Command 9. Add values to command parameters if any 10. Specify the SelectCommand for the DataAdapter 11. Fill the DataSet with the result set from the database table 12. Create a new DataRow object 13. Assign values for each of it's field 14. Add the DataRow object to the specified DataTable of the DataRow 15. Send the changes to the database We need to retrieve the contents of a database table that we wan't to add a record. That is why we still need to specify the SelectCommand for the DataAdapter. After that, we can make any changes to the DataTable containing the results. We can add a new DataRow representing the new record in it's Rows property. To demonstrate the steps above, create a new Windows Forms Application and name it InsertingRecordsDisconnected. Add labels and text boxes for FirstName, LastName, Gender, Age, and Address fields. Name the textboxes firstNameTextBox, lastNameTextBox, genderTextBox, ageTextBox, and addressTextBox. Also add a button and name it addButton.

Figure 1 COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Double click the button to generate an event handler for its Click event. Import the System.Data and System.Data.SqlClient. Use the following code for the handler. 1 private void addButton_Click(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 SqlDataAdapter adapter = new SqlDataAdapter(); 6 SqlCommandBuilder builder = new SqlCommandBuilder(adapter); 7 DataSet dataset = new DataSet(); 8 9 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 10 "Initial Catalog=University;Integrated Security=SSPI"; 11 command.Connection = connection; 12 command.CommandText = "SELECT * FROM Students"; 13 adapter.SelectCommand = command; 14 adapter.Fill(dataset, "Students"); 15 16 DataRow row = dataset.Tables["Students"].NewRow(); 17 row["FirstName"] = firstNameTextBox.Text; 18 row["LastName"] = lastNameTextBox.Text; 19 row["Gender"] = genderTextBox.Text; 20 row["Age"] = Int32.Parse(ageTextBox.Text); 21 row["Address"] = addressTextBox.Text; 22 23 dataset.Tables["Students"].Rows.Add(row); 24 25 try 26 { 27 int result = adapter.Update(dataset, "Students"); 28 29 if (result > 0) 30 MessageBox.Show("Success!"); 31 else 32 MessageBox.Show("Failed!"); 33 } 34 catch (SqlException ex) 35 { 36 MessageBox.Show(ex.Message); 37 } 38}

Example 2 We created the necessary objects in lines 3-7. Note the create of SqlCommandBuilder in line 6. In its constructor, we pass the created DataAdapter object to associate the CommandBuilder to it. Lines 12-14 fills the DataSet of values from the Student table and adds the result to the DataTable named Students inside the DataSet. Now that we have the values of the table from the database, we can now insert values to that DataTable. Line 16 creates a new DataRow object which represents the row of a DataTable. We specify which Table the row will be added and used the DataTable's NewRow() method. Doing this instead of intializing a DataRow using a constructor saves automatically provides the necessary columns for the DataRow together with their associated column names. Lines 17-21 accesses each column using the DataRow's indexer

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

that accepts the name of the column. We assigned each of the value of every text box. In line 23, we added the row to the Rows property of the DataTable that contains the records. We have now modifies the DataTable because we added a new record, but the record is only added to the DataTable, not the actual database table. Line 27 calls the DataAdapter's Update() method and we passed the DataSet and the name of the DataTable. When Update() is called, the CommandBuilder generates the required SQL statements for every changes or modification it detects. Those SQL commands are then executed to the database. In our case, since we added a new row to the DataTable, CommandBuilder generates an INSERT Statement together with parameters filled with the values you specified. After the execution of the command, the values is then added to the actual database table. The Update() method returns an integer value representing the number of row affected. Since we inserted 1 row, then we are expecting a return value of 1. We test if the result is greater than 0 in line 29. If it is, then we show a success message. Otherwise, we tell the user that the insertion has failed. Execute the program and provide a value to be added to the database table.

Clicking the Add Student button will add the values to the DataTable and the changes will be sent to the database where a new row will be added to the actual database table.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Deleting Records: Connected Approach We will now delete a database record using the connected approach. The steps are the same as inserting a record while connected to a database which uses the DbCommand.ExecuteNonQuery() method. 1. 2. 3. 4. 5. 6. 7. 8. 9.

Create a Connection Create a Command Specify connection string to Connection Specify Connection that the Command will use Specify the DELETE Statement for the CommandText of the Command Add values to command parameters if any Open Connection Execute the command Close Connection

Let's create a simple application that allows you to specify the StudentId and delete the corresponding record having that ID. Create a new Windows Forms Application and name it DeletingRecordsConnected. Add a label and text box for the StudentID and a button that will execute the commands. Name the text box studentIdTextBox and the button as deleteButton.

Figure 1 Double click the button to generate an event handler for its Click event. Be sure to import the System.Data.SqlClient namespace. Use the following code for the event handler. 1 private void button1_Click(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 7 "Initial Catalog=University;Integrated Security=SSPI"; 8 command.Connection = connection; 9 command.CommandText = "DELETE FROM Students WHERE 10StudentID=@StudentID"; 11 command.Parameters.AddWithValue("@StudentID", studentIdTextBox.Text); 12 13 try 14 {

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

connection.Open(); int result = command.ExecuteNonQuery(); if (result > 0) MessageBox.Show("Student was removed!"); else MessageBox.Show("Can't find student."); } catch (SqlException ex) { MessageBox.Show("An error has occured."); } finally { connection.Close(); } }

Example 2 Line 9 specified a DELETE SQL Statement which has 1 command parameter, the StudentID to be deleted. Line 10 add's the text of the studentIdTextBox as a value to that command parameter. Inside the try block, we opened the connection and Line 15 uses the ExecuteNonQuery() method to execute the DELETE command. The method returns an integer which is the number of rows affected. Line 16 tested if at least 1 row was affected since we delete 1 record. If so, we show a message showing that the deletion was successful. If no records were affected, it simply means the record was not found and no records where deleted. Run the program and type a StudentId that exist in the Students table.

If a matching row is found, it is removed from the table.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Deleting Records: Disconnected Approach Deleting database using the disconnected approach is simillar to inserting a row using the DataSet and the DataAdapter classes. But instead of adding a new DataRow object, you will delete it from the DataTable of the DataSet. The following are the basic steps to delete a row using disconnected approach. 1. Create a Connection 2. Create a Command 3. Create a DataAdapter 4. Create a CommandBuilder and associate it to the DataAdapter 5. Create a DataSet 6. Specify connection string for the connection 7. Specify Connection to be used by the Command 8. Specify CommandText for the Command 9. Add values to command parameters if any 10. Specify the SelectCommand for the DataAdapter 11. Fill the DataSet with the result set from the database table 12. Find the row to delete. 13. Delete the row from the DataTable if found. 14. Send the changes to the database Let's create a simple application that allows you to specify the StudentId and delete the corresponding record having that ID. Create a new Windows Forms Application and name it DeletingRecordDisconnected. Add a label and text box for the StudentID and a button that will execute the commands. Name the text box studentIdTextBox and the button as deleteButton.

Figure 1 Double click the button to generate an event handler for its Click event. Be sure to import the System.Data.SqlClient namespace. Use the following code for the event handler. 1 private void deleteButton_Click(object sender, EventArgs e) 2 { 3 4 SqlConnection connection = new SqlConnection(); 5 SqlCommand command = new SqlCommand(); 6 SqlDataAdapter adapter = new SqlDataAdapter(); 7 SqlCommandBuilder builder = new SqlCommandBuilder(adapter);

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39}

DataSet dataset = new DataSet(); connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + "Initial Catalog=University;Integrated Security=SSPI"; command.Connection = connection; command.CommandText = "SELECT * FROM Students"; adapter.SelectCommand = command; adapter.Fill(dataset, "Students"); foreach (DataRow row in dataset.Tables["Students"].Rows) { if (row["StudentID"].ToString() == studentIdTextBox.Text) { row.Delete(); } } try { int result = adapter.Update(dataset, "Students"); if (result > 0) MessageBox.Show("Success!"); else MessageBox.Show("Failed!"); } catch (SqlException ex) { MessageBox.Show(ex.Message); }

Example 1 We created the necessary objects in lines 4-8. Note the create of SqlCommandBuilder in line 7. In its constructor, we pass the created DataAdapter object to associate the CommandBuilder to it. Lines 13-15 fills the DataSet of values from the Student table and adds the result to the DataTable named Students inside the DataSet. Now that we have the values of the table from the database, we can now delete a row from that DataTable. We first need to search which record to delete. We used a foreach loop (line 17-24) to iterate through each record in the DataSet. Line 19 tests whether the content of the StudentID field of the current row is equal to what the user specified in the studentIdTextBox. If it matches, we use the DataRow.Delete() method to delete that row from the table. Line 28 calls the DataAdapter's Update() method and we passed the DataSet and the name of the DataTable. When Update() is called, the CommandBuilder generates the required SQL statements for every changes of modification it detects. Those SQL commands are then executed to the database. In our case, since we deleate a row from the DataTable, CommandBuilder generates a DELETE Statement together with parameters filled with the values you specified. After the execution of the command, the row or rows are deleted from the actual database table. The Update() method returns an integer value representing the number of row affected. Since we

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

1 row was deleted, we are expecting a return value of 1. We test if the result is greater than 0 in line 30. If it is, then we show a success message. Otherwise, we tell the user that the deletion of the row has failed. Run the program and type a StudentId that exist in the Students table.

Figure 2 If a matching row is found, it is removed from the table.

Figure 3

Updating Records: Connected Approach We will now take a look at updating fields of records in a database table. Like inserting and deleting records, updating also uses the DbCommand.ExecuteNonQuery() method. The steps is pretty much similar when updating a record using the connected approach. 1. 2. 3. 4. 5. 6. 7. 8. 9.

Create a Connection Create a Command Specify connection string to Connection Specify Connection that the Command will use Specify the UPDATE statement for the CommandText of the Command Add values to command parameters if any Open Connection Execute the Command Close Connection

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The steps above are used for updating a record. Let's take a look at an example application. You type the StudentID and the new values for the fields corresponding to the ID. In a more realistic program, the current values will be shown first to you. But for simplicity, we will only show Therefore, we need to query values from the database. After the details are shown, the user can then edit details and send the changes to the database. Create a new Windows Forms Application and name it UpdatingRecordsConnected.

Label 1 2 3 4 5 6 7

Name textBoxStudentID textBoxFirstName textBoxLastName textBoxGender textBoxAge textBoxAddress buttonUpdate

Figure 1 Double click the Update button to generate an event handler for its Click event. Use the following code: 1 private void buttonUpdate_Click(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" +

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39}

"Initial Catalog=University;Integrated Security=SSPI"; command.Connection = connection; command.CommandText = "UPDATE Students SET FirstName=@FirstName, " + "LastName=@LastName, Gender=@Gender, Age=@Age, Address=@Address " + "WHERE StudentID=@StudentID"; command.Parameters.Clear(); command.Parameters.AddWithValue("@FirstName", textBoxFirstName.Text); command.Parameters.AddWithValue("@LastName", textBoxLastName.Text); command.Parameters.AddWithValue("@Gender", textBoxGender.Text); command.Parameters.AddWithValue("@Age", textBoxAge.Text); command.Parameters.AddWithValue("@Address", textBoxAddress.Text); command.Parameters.AddWithValue("@StudentID", textBoxStudentID.Text); try { connection.Open(); int result = command.ExecuteNonQuery(); if (result > 0) MessageBox.Show("Update Successful!"); else MessageBox.Show("Update Failed!"); } catch (SqlException ex) { MessageBox.Show("An error occured."); } finally { connection.Close(); }

Example 1 Lines 9-11 specifies the UPDATE SQL command that will be used to update the row specified by the StudentID of its WHERE clause. We used command parameters on the command. Line 13 first clears any content of the Parameters property of our command because it may still contain the parameters of previous operation. Lines 14-19 uses the DbParameter.AddWithValue() method to add values to corresponding command parameters in our SQL command string. Since an SQL UPDATE is a non-query command (it doesn't return any records or results), line 24 uses the DbCommand.ExecuteNonQuery() method to update the specified record. The return value of this method is the number of rows affected. To confirm that a record was successfully updated, we checked if the result is 1 or above (line 26) and then we showed a success message. Run the program and type the StudentID you wan't to edit along with the new values it will contain.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

If no error is found, then a success message will pop out and the record in the database table will be modified.

The program in this lesson simple shows how to update a record. But it will be hard to update a record without knowing the current values first. A seperate tutorial will apply everything we have learned (querying, inserting, deleting, updating). But first, let's take a look at how to update records using the disconnected approach.

Updating Records: Disconnected Approach We will now take a look at updating records using the disconnected approach. Like inserting and deleting records using the disconnected approach, updating records also uses the DataAdapter, DataSet, and CommandBuilder classes to do it's job. The following are the basic steps for updating a record using the said classes. 1. 2. 3. 4. 5. 6.

Create a Connection Create a Command Create a DataAdapter Create a CommandBuilder and associate it to the DataAdapter Create a DataSet Specify connection string for the connection

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

7. Specify Connection to be used by the Command 8. Specify the SELECT statement for the CommandText of the Command 9. Add values to command parameters if any 10. Specify the SelectCommand for the DataAdapter 11. Fill the DataSet with the result set from the database table 12. Find the row to update. 13. Edit the fields you want to update 14. Send the changes to the database The following example application allows you to update a certain record of a student based on the StudentID. A typical application like this would normally show the current values of the record first, but for simplicity, we will go straight to the updating. You will simply need to type the StudentID and then the new values for the corresponding record. Create a new Windows Forms Application and create a form similar to the following one.

Label Name 1 textBoxStudentId 2 textBoxFirstName 3 textBoxLastName 4 textBoxGender 5 textBoxAge 6 textBoxAddress 7 buttonUpdate Figure 1

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

After creating the GUI, double click buttonUpdate and use the following event handler for its Click event. 1 private void buttonUpdate_Click(object sender, EventArgs e) 2 { 3 SqlConnection connection = new SqlConnection(); 4 SqlCommand command = new SqlCommand(); 5 SqlDataAdapter adapter = new SqlDataAdapter(); 6 SqlCommandBuilder builder = new SqlCommandBuilder(adapter); 7 DataSet dataset = new DataSet(); 8 9 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 10 "Initial Catalog=University;Integrated Security=SSPI"; 11 command.Connection = connection; 12 command.CommandText = "SELECT * FROM Students"; 13 14 adapter.SelectCommand = command; 15 adapter.Fill(dataset, "Students"); 16 17 foreach (DataRow row in dataset.Tables["Students"].Rows) 18 { 19 if (row["StudentID"].ToString() == textBoxStudentID.Text) 20 { 21 row["FirstName"] = textBoxFirstName.Text; 22 row["LastName"] = textBoxLastName.Text; 23 row["Gender"] = textBoxGender.Text; 24 row["Age"] = textBoxAge.Text; 25 row["Address"] = textBoxAddress.Text; 26 } 27 } 28 29 try 30 { 31 int result = adapter.Update(dataset, "Students"); 32 33 if (result > 0) 34 MessageBox.Show("Update Successful."); 35 else 36 MessageBox.Show("Update Failed."); 37 } 38 catch (SqlException ex) 39 { 40 MessageBox.Show(ex.Message); 41 } 42}

Example 1 After initializing the required variables, we first need to transfer the contents of the table in a dataset so we will have an in-memory database that we can work with. That's why, we use the SELECT command and used the DbDataAdapter.Fill() method to retrieve all the records from the Students table. Updating using disconnected approach does not require an UPDATE Sql command. The UPDATE command will be generated by the SqlCommandBuilder object. The update will be done using searching and simple value assignment with C#.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Line 17 uses a foreach loop to check each row. We used the appropriate table from the dataset as the source. Remember that each row in a DataTable is of type DataRow. Line 19 checks if the StudentID field of the current DataRow is equal to the specified StudentID in the textboxStudentID. If so, then inside the if statement, we update each of the field of that DataRow to the new values from the textboxes. After that, we simply need to call the DbDataAdapter.Update() method to send the changes to the database (line 31). This method accepts two arguments, the dataset where the updated row is contained, and the name of the table in that dataset (not the database table). If the method is successful at updating the actual database table, then the number of rows updated is returned. We simply assign the value returned in a variable so we can test if the update was successful, that is, if the value returned is not 0. Run the program and type the StudentID of an existing student. Type new values for each text box.

Click the update button to initiate the update process. If everything is working properly, then you will be presented with a success message.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The program in this lesson simple shows how to update a record. But it will be hard to update a record without knowing the current values first. A seperate tutorial will apply everything we have learned (querying, inserting, deleting, updating).

Simple Student Enrollment System - Connected Approach We will create a Simple Enrollment System that allows you to search for an student in the database using a specified StudentID. It will also allow you to add or remove a student from the database or update his/her student information. We will use the connected approach for querying, inserting, removing, and updating records. The next tutorial will show another version showing how to create the same project using the disconnected version. Create a new windows forms application and create a user interface similar to the one shown in Figure 1.

Figure 1 Label Name Properties 1 textBoxStudentId 2 textBoxFirstName Enabled: False 3 textBoxLastName Enabled: False 4 textBoxGender Enabled: False

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Label Name 5 textBoxAge 6 textBoxAddress 7 buttonDelete 8 buttonEdit 9 buttonAddNew 10 buttonShow

Properties Enabled: False Enabled: False Text: Delete Text: Edit Text: Add New Text: Show

Figure 2 Go to the Code Editor by pressing F7 and be sure to first import the two neccessary namespaces for this database connection. using System.Data; using System.Data.SqlClient;

Add the following private fields into the Form1 class: private private private private private

SqlConnection connection; SqlCommand command; SqlDataReader reader; bool updateReady; bool insertReady;

We declared the fields that will be used for connecting and issuing commands to the database. We declared them as class fields instead of as local variables so they will be shared by all database operations (For example, no need to declare Connection objects for querying and another one for inserting records). The updateReady and inserReady field will be used later for updating and inserting new students. On the Form's constructor add the codes in lines 5-11. 1 public Form1() 2 { 3 InitializeComponent(); 4 5 connection = new SqlConnection(); 6 command = connection.CreateCommand(); 7 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 8 "Initial Catalog=University; Integrated Security=SSPI"; 9 10 updateReady = false; 11 insertReady = false; 12}

Example 1 Line 5 initializes our Connection object. Line 6 uses the DbConnection.CreateCommand() method which returns an DbCommand object that is already connected to the DbConnection object that calls that method. In this case, calling the CreateCommand() method returns an

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

SqlCommand object with its Connection property already referring to the SqlConnection object. Line 7-8 indicates the connection string for the connection. Lines 10-11 sets the updateReady and insertReady flags to false. This simply means that the program is initially not allowing an update or addition of new students. The text fields except the StudentID are initially disabled so no updates or insertions can be made. The program for now can only do queries to the database by typing the StudentId in textBoxStudentId and clicking the buttonShow. The code for the Click event of buttonShow is as follows: private void buttonShow_Click(object sender, EventArgs e) 1 { 2 command.CommandText = "SELECT * FROM Students WHERE 3 StudentID=@StudentID"; 4 command.Parameters.Clear(); 5 command.Parameters.AddWithValue("@StudentID", textBoxStudentID.Text); 6 7 try 8 { 9 connection.Open(); 10 reader = command.ExecuteReader(CommandBehavior.SingleRow); 11 12 if (reader.Read()) 13 { 14 textBoxFirstName.Text = reader["FirstName"].ToString(); 15 textBoxLastName.Text = reader["LastName"].ToString(); 16 textBoxGender.Text = reader["Gender"].ToString(); 17 textBoxAge.Text = reader["Age"].ToString(); 18 textBoxAddress.Text = reader["Address"].ToString(); 19 } 20 else 21 MessageBox.Show("StudentID does not exist."); 22 } 23 catch (SqlException ex) 24 { 25 MessageBox.Show(ex.Message); 26 } 27 finally 28 { 29 connection.Close(); 30 } 31 }

Example 2 Since we declared our Connection and Command objects as class fields, we can simply change the properties of them depending on the operation to be made. Line 3 changes the CommandText property of our Command object to a SELECT statement the retrieves everything from the Students table that has a StudentID specified. The command text has one command parameter for StudentID which will be replaced by the value typed by the user in textBoxStudentID as shown in line 5. Note that before that, we cleared the Parameters property first because it might already contain some values from other operation. We do that using the Clear() method (line 4). Inside a try block, we first open the connection and create a SqlDataReader using the DbCommand.ExecuteReader() method. We passed CommandBehavior.SingleRow value as an

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

argument to that method so the reader will only return one record which is the record of the student we are searching. Line 12 uses the Read() method to retrieve that single record from the database. If it is successful, then the method will return true, and inside the if statement, we show the values of each column of that record to their respective text boxes. The rest of the code are used when no record is found and when an SqlException is thrown. Don't forget to close the connection as shown in Line 29. Next in the list is the buttonAddNew which is responsible for adding or "enrolling" new students to the database. The following is the event handler for the buttonAddNew's Click event. 1 private void buttonAddNew_Click(object sender, EventArgs e) 2 { 3 if (!insertReady) 4 { 5 buttonAddNew.Text = "Enroll"; 6 ClearFields(); 7 textBoxStudentID.Text = GetNextStudentID().ToString(); 8 9 textBoxStudentID.Enabled = false; 10 textBoxFirstName.Enabled = true; 11 textBoxLastName.Enabled = true; 12 textBoxGender.Enabled = true; 13 textBoxAge.Enabled = true; 14 textBoxAddress.Enabled = true; 15 buttonShow.Enabled = false; 16 buttonEdit.Enabled = false; 17 buttonDelete.Enabled = false; 18 insertReady = true; 19 } 20 else 21 { 22 buttonAddNew.Text = "Add New"; 23 24 command.CommandText = "INSERT INTO Students " + 25 "(FirstName, LastName, Gender, Age, Address) VALUES " + 26 "(@FirstName, @LastName, @Gender, @Age, @Address)"; 27 command.Parameters.Clear(); 28 command.Parameters.AddWithValue("@FirstName", 29textBoxFirstName.Text); 30 command.Parameters.AddWithValue("@LastName", textBoxLastName.Text); 31 command.Parameters.AddWithValue("@Gender", textBoxGender.Text); 32 command.Parameters.AddWithValue("@Age", textBoxAge.Text); 33 command.Parameters.AddWithValue("@Address", textBoxAddress.Text); 34 35 try 36 { 37 connection.Open(); 38 39 int result = command.ExecuteNonQuery(); 40 41 if (result > 0) 42 MessageBox.Show("Student successfully enrolled."); 43 else 44 MessageBox.Show("Failed to enroll student.");

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

} catch (SqlException ex) { MessageBox.Show(ex.Message); } finally { connection.Close(); } textBoxStudentID.Enabled = true; textBoxFirstName.Enabled = false; textBoxLastName.Enabled = false; textBoxGender.Enabled = false; textBoxAge.Enabled = false; textBoxAddress.Enabled = false; buttonShow.Enabled = true; buttonEdit.Enabled = true; buttonDelete.Enabled = true; insertReady = false; } }

Example 3 The buttonAddNew will serve as a toggle button. The insertReady field will determine the action that this button will perform. Since insertReady is initially false, lines 5-18 will be executed. Line 5 changes the text of the button to "Enroll" simply to notify the user that this button should be clicked once the details are entered. Line 6 calls a method that will clear all the fields if so it will be ready to accept new details from the user. The definition for the ClearFields() method is as follows: private void ClearFields() { textBoxFirstName.Text = String.Empty; textBoxLastName.Text = String.Empty; textBoxGender.Text = String.Empty; textBoxAge.Text = String.Empty; textBoxAddress.Text = String.Empty; }

Example 4 Since we need will be adding a new student, we need to generate the next unique StudentID. We can't simply type a new student ID because the same student ID may already be in the database. That's why, line 7 calls another utility method called GetNextStudentID(). The defnition for this method is as follows: 1 private int GetNextStudentID() 2 { 3 command.CommandText = "SELECT IDENT_CURRENT('Students') + 4 IDENT_INCR('Students')"; 5

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

try { connection.Open(); int nextID = Convert.ToInt32(command.ExecuteScalar()); return nextID; } catch (SqlException ex) { MessageBox.Show(ex.Message); } finally { connection.Close(); } return 0; }

Example 5 Line 3 creates an SQL Server command that will get the next Identity field value. Remember that the StudentID field of the Students table is an Identity field which auto increments when new records are added. The thing is, we can't simply get the last StudentID and add 1 because SQL server saves the last Identity value used so if we delete a record with StudentID 5, making the new last StudentID is 4, the next StudentID that will be generated will be 6. There is an SQL Server function called IDENT_CURRENT() which returns the current identity field and IDENT_INCR() which returns the increment value of the identity field. We passed the name of the table to these functions and added their return values to get the latest StudentID. We open the connection in line 7 and line 8 uses the DbCommand.ExecuteScalar() since we are expecting a single value (not record) to be returned. The value is the generated last StudentID but we need to convert it first to integer. Finally, wer returned that value to the caller of the method (line 9). Back to the code in Example 3, after getting a new StudentID, we simply display it using textBoxStudentID. Lines 9-14 enables the text boxes so the user can enter the details for the new student and lines 15-17 disables buttonShow, buttonInsert, and buttonDelete so the user can only click the "Enroll" button. Finally, line 18 changes the value of insertReady to true so the next time the user clicks this button, lines 22-63 will be executed instead. The first time the user clicks the buttonAddNew, the program is now ready to accept the information for the new student. After the user types the information for each field, the user should now then click the buttonAddNew again to execute the SQL INSERT command to the database. Let's now discuss lines 22-63 of Example 3 which does the actual communication to the database. Line 22 reverts back the label of the button to "Add New". Lines 24-26 changes the CommandText property of the Command object to an SQL INSERT statement. The command has 5 command properties for each field. Note that the StudentID was not included because it will automatically generated by SQL Server. Line 27 ensures that no existing command parameter values are in the Parameters collection of the Command object by using the Clear() method. Lines 28-32 assigns the value of each text box to their corresponding command parameter. After everything is set and the connection is openned, Line 38 uses the DbCommand.ExecuteNonQuery() method to execute the command to the database. Lines 54-63

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

disables the text boxes again and reenables the disabled buttons. The insertReady fields was also set a value of false to indicate the insertion process is complete and the user is required to click this button again if he/she will be adding another student. The buttonEdit also acts as a toggle button and most of the code is similar to the code of buttonAddNew. 1 private void buttonEdit_Click(object sender, EventArgs e) 2 { 3 if (!updateReady) 4 { 5 buttonEdit.Text = "Update"; 6 textBoxStudentID.Enabled = false; 7 textBoxFirstName.Enabled = true; 8 textBoxLastName.Enabled = true; 9 textBoxGender.Enabled = true; 10 textBoxAge.Enabled = true; 11 textBoxAddress.Enabled = true; 12 buttonShow.Enabled = false; 13 buttonAddNew.Enabled = false; 14 buttonDelete.Enabled = false; 15 updateReady = true; 16 } 17 else 18 { 19 buttonEdit.Text = "Edit"; 20 21 command.CommandText = "UPDATE Students SET FirstName=@FirstName, " 22+ 23 "LastName=@LastName, Gender=@Gender, Age=@Age, Address=@Address 24" + 25 "WHERE StudentID=@StudentID"; 26 command.Parameters.Clear(); 27 command.Parameters.AddWithValue("@FirstName", 28textBoxFirstName.Text); 29 command.Parameters.AddWithValue("@LastName", textBoxLastName.Text); 30 command.Parameters.AddWithValue("@Gender", textBoxGender.Text); 31 command.Parameters.AddWithValue("@Age", textBoxAge.Text); 32 command.Parameters.AddWithValue("@Address", textBoxAddress.Text); 33 command.Parameters.AddWithValue("@StudentID", 34textBoxStudentID.Text); 35 36 try 37 { 38 connection.Open(); 39 int result = command.ExecuteNonQuery(); 40 41 if (result > 0) 42 MessageBox.Show("Student details successfully updated."); 43 else 44 MessageBox.Show("Update failed."); 45 } 46 catch (SqlException ex) 47 { 48 MessageBox.Show(ex.Message);

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

49 50 51 52 53 54 55 56 57 58 59 60 61 62

} finally { connection.Close(); } textBoxStudentID.Enabled = true; textBoxFirstName.Enabled = false; textBoxLastName.Enabled = false; textBoxGender.Enabled = false; textBoxAge.Enabled = false; textBoxAddress.Enabled = false; buttonShow.Enabled = true; buttonAddNew.Enabled = true; buttonDelete.Enabled = true; updateReady = false; } }

Example 6 Clicking the buttonEdit for the first time will enable the text boxes and disable the buttons except the buttonEdit itself. We used the updateReady field to make the button toggle its functionality. After the changes has been made to the current student, clicking the button the second time will send the changes to the database. Lines 19-60 does this and the codes you just need to edit are the SQL command and the parameter values. Finally, the buttonDelete's Click event handler is shown in Example 7. 1 private void buttonDelete_Click(object sender, EventArgs e) 2 { 3 command.CommandText = "DELETE FROM Students WHERE 4 StudentID=@StudentID"; 5 command.Parameters.Clear(); 6 command.Parameters.AddWithValue("@StudentID", textBoxStudentID.Text); 7 8 try 9 { 10 connection.Open(); 11 12 int result = command.ExecuteNonQuery(); 13 14 if (result > 0) 15 { 16 MessageBox.Show("Student successfully deleted."); 17 ClearFields(); 18 } 19 else 20 MessageBox.Show("Failed to delete student."); 21 } 22 catch (SqlException ex) 23 { 24 MessageBox.Show(ex.Message); 25 }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

26 27 28 29

finally { connection.Close(); } }

Example 7 We just changed the CommandText property of the command into a SQL DELETE statement that contains one command parameter which is the StudentID to delete. After specifying the command, adding the value for the command parameter, and openning the connection, line 11 uses the ExecuteNonQuery() method to actually delete record with the specified StudentID fromt he database table. Our simple enrollment system is now complete. To test it, run the program and type an existing StudentID in the first text box. Click the show button to see the student's information. If you want to edit those information, you can click the buttonEdit, type the new values, and click buttonEdit again to save the changes. You can also delete that student by clicking buttonDelete. To add or enroll a new student, click the buttonAddNew and type the information of the new student into the fields. Click the buttonAddNew once more to add the student into the Students database table. Download Project: SimpleEnrollmentSystemConnected.rar

Simple Student Enrollment System - Disconnected Approach We will create a Simple Enrollment System that allows you to search for an student in the database using a specified StudentID. It will also allow you to add or remove a student from the database or update his/her student information. This lesson will use the disconnected approach for querying, inserting, removing, and updating records. Create a new windows forms application and create a user interface similar to the one shown in Figure 1.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Figure 1 Label Name Properties 1 textBoxStudentId 2 textBoxFirstName Enabled: False 3 textBoxLastName Enabled: False 4 textBoxGender Enabled: False 5 textBoxAge Enabled: False 6 textBoxAddress Enabled: False 7 buttonDelete Text: Delete 8 buttonEdit Text: Edit 9 buttonAddNew Text: Add New 10 buttonShow Text: Show Figure 2 Go to the Code Editor by pressing F7 and be sure to first import the two neccessary namespaces for this database connection. using System.Data; using System.Data.SqlClient;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Add the following private fields into the Form1 class: private SqlConnection connection; private SqlCommand command; private SqlDataAdapter adapter; private SqlCommandBuilder builder; private DataSet dataSet; bool updateReady = false; bool insertReady = false;

We declared the fields that will be used for connecting and issuing commands to the database. We declared them as class fields instead of as local variables so they will be shared by all database operations (For example, no need to declare Connection objects for querying and another one for inserting records). The updateReady and inserReady field will be used later for updating and inserting new students. On the Form's constructor add the codes in lines 5-11. 1 public Form1() 2 { 3 InitializeComponent(); 4 5 connection = new SqlConnection(); 6 connection.ConnectionString = @"Data Source=.\SQLEXPRESS;" + 7 "Initial Catalog=University;Integrated Security=SSPI"; 8 9 command = connection.CreateCommand(); 10 adapter = new SqlDataAdapter(command); 11 builder = new SqlCommandBuilder(adapter); 12 dataSet = new DataSet(); 13}

Example 1 Line 5 initializes our Connection object. Line 6 specifies the connection string that will be used for connection. Line 9 creates the command using the DbCommand.CreateCommand() method which returns a Command object that is already assigned to the Connection object that called that method. Line 10 creates a DataAdapter object and we passed the Command object that will be used as the SelectCommand inside its constructor. Line 11 passes the created DataAdapter in the constructor of the CommandBuilder object which will be used to generate SQL commands when the Update() method is called later. Finally, line 12 creates a DataSet() object which will contain the result sets obtained from the database. The program for now can only do queries to the database by typing the StudentId in textBoxStudentId and clicking the buttonShow. The code for the Click event of buttonShow is as follows: 1 private void buttonShow_Click(object sender, EventArgs e) 2 { 3 command.CommandText = "SELECT * FROM Students WHERE 4 StudentID=@StudentID"; 5 command.Parameters.Clear(); 6 command.Parameters.AddWithValue("@StudentID", textBoxStudentID.Text); 7 8 dataSet.Tables.Clear(); 9

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

int result = adapter.Fill(dataSet, "Students"); if (result > 0) { DataRow student = dataSet.Tables["Students"].Rows[0]; textBoxFirstName.Text = student["FirstName"].ToString(); textBoxLastName.Text = student["LastName"].ToString(); textBoxGender.Text = student["Gender"].ToString(); textBoxAge.Text = student["Age"].ToString(); textBoxAddress.Text = student["Address"].ToString(); } else { ClearFields(); MessageBox.Show("Student does not exist."); } }

Example 2 Since we declared our Connection and Command objects as class fields, we can simply change the properties of them depending on the operation to be made. Line 3 changes the CommandText property of our Command object to a SELECT statement the retrieves everything from the Students table that has a StudentID specified. The command text has one command parameter for StudentID which will be replaced by the value typed by the user in textBoxStudentID as shown in line 5. Note that before that, we cleared the Parameters property first because it might already contain some values from other operation. We do that using the Clear() method (line 4). Line 7 clears the Tables collection property of the dataset incase there are already tables stored in it. Line 9 calls the DbDataAdapter.Fill() method to query the student from the database table and add it to a table named "Students" in the dataSet. The Fill() method will return the number of rows or result sets returned and we are expecting at least 1 so line 11 tests if the value returned is greater than 0. If so line 13 first stores the first row of the Students table in the dataSet into a DataRow object for easier typing and readablity although it is optional. Lines 14-18 shows the values of individual columns of the retrieved student row into their respective text boxes. Lines 20-24 are codes to be executed if no student with the specified student number is returned or found. Next in the list is the buttonAddNew which is responsible for adding or "enrolling" new students to the database. The following is the event handler for the buttonAddNew's Click event. 1 private void buttonAddNew_Click(object sender, EventArgs e) 2 { 3 if (!insertReady) 4 { 5 buttonAddNew.Text = "Enroll"; 6 ClearFields(); 7 textBoxStudentID.Text = GetNextStudentID().ToString(); 8 9 textBoxStudentID.Enabled = false; 10 textBoxFirstName.Enabled = true; 11 textBoxLastName.Enabled = true; 12 textBoxGender.Enabled = true;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62}

textBoxAge.Enabled = true; textBoxAddress.Enabled = true; buttonShow.Enabled = false; buttonEdit.Enabled = false; buttonDelete.Enabled = false; insertReady = true; } else { buttonAddNew.Text = "Add New"; command.CommandText = "SELECT * FROM Students"; dataSet.Tables.Clear(); adapter.Fill(dataSet, "Students"); DataRow row = dataSet.Tables["Students"].NewRow(); row["FirstName"] = textBoxFirstName.Text; row["LastName"] = textBoxLastName.Text; row["Gender"] = textBoxGender.Text; row["Age"] = textBoxAge.Text; row["Address"] = textBoxAddress.Text; dataSet.Tables["Students"].Rows.Add(row); try { int result = adapter.Update(dataSet, "Students"); if (result > 0) MessageBox.Show("Student successfully enrolled."); else MessageBox.Show("Failed to enroll student."); } catch (SqlException ex) { MessageBox.Show(ex.Message); } textBoxStudentID.Enabled = true; textBoxFirstName.Enabled = false; textBoxLastName.Enabled = false; textBoxGender.Enabled = false; textBoxAge.Enabled = false; textBoxAddress.Enabled = false; buttonShow.Enabled = true; buttonEdit.Enabled = true; buttonDelete.Enabled = true; insertReady = false; }

Example 3 The buttonAddNew will serve as a toggle button. The insertReady field will determine the action that this button will perform. Since insertReady is initially false, lines 5-18 will be executed.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Line 5 changes the text of the button to "Enroll" simply to notify the user that this button should be clicked once the details are entered. Line 6 calls a method that will clear all the fields if so it will be ready to accept new details from the user. The definition for the ClearFields() method is as follows: private void ClearFields() { textBoxFirstName.Text = String.Empty; textBoxLastName.Text = String.Empty; textBoxGender.Text = String.Empty; textBoxAge.Text = String.Empty; textBoxAddress.Text = String.Empty; }

Example 4 Since we need will be adding a new student, we need to generate the next unique StudentID. We can't simply type a new student ID because the same student ID may already be in the database. That's why, line 7 calls another utility method called GetNextStudentID(). The defnition for this method is as follows: private int GetNextStudentID() 1 { 2 command.CommandText = "SELECT IDENT_CURRENT('Students') + 3 IDENT_INCR('Students')"; 4 5 try 6 { 7 connection.Open(); 8 int nextID = Convert.ToInt32(command.ExecuteScalar()); 9 return nextID; 10 } 11 catch (SqlException ex) 12 { 13 MessageBox.Show(ex.Message); 14 } 15 finally 16 { 17 connection.Close(); 18 } 19 return 0; 20 }

Example 5 Line 3 creates an SQL Server command that will get the next Identity field value. Remember that the StudentID field of the Students table is an Identity field which auto increments when new records are added. The thing is, we can't simply get the last StudentID and add 1 because SQL server saves the last Identity value used so if we delete a record with StudentID 5, making the new last StudentID is 4, the next StudentID that will be generated will be 6. There is an SQL Server function called IDENT_CURRENT() which returns the current identity field and IDENT_INCR() which returns the increment value of the identity field. We passed the name of COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

the table to these functions and added their return values to get the latest StudentID. We open the connection in line 7 and line 8 uses the DbCommand.ExecuteScalar() since we are expecting a single value (not record) to be returned. The value is the generated last StudentID but we need to convert it first to integer. Finally, wer returned that value to the caller of the method (line 9). Note that this method used the connected approach for obtaining a single value. You can also retrieve the value using the disconnected way. Back to the code in Example 3, after getting a new StudentID, we simply display it using textBoxStudentID. Lines 9-14 enables the text boxes so the user can enter the details for the new student and lines 15-17 disables buttonShow, buttonInsert, and buttonDelete so the user can only click the "Enroll" button. Finally, line 18 changes the value of insertReady to true so the next time the user clicks this button, lines 22-60 will be executed instead. The first time the user clicks the buttonAddNew, the program is now ready to accept the information for the new student. After the user types the information for each field, the user should now then click the buttonAddNew again to execute the SQL INSERT command to the database. Let's now discuss lines 22-63 of Example 3 which does the actual communication to the database. Line 22 reverts back the label of the button to "Add New". Lines 24 changes the CommandText property of our Command object into a SELECT Statement that queries all records form the database.Line 25 resets the Tables property to remove any tables that might be there. Line 26 Fills the dataSet with all the records from the database table. Line 28 uses the DataTable.NewRow() method to create a DataRow with the same number of columns and type as the Row found in the Students table of the dataSet. If you will not use NewRow(), then you will need to manually create each column witch would be tedious. Lines 29-33 simply assigns the values in the text box to each column of the new row to be added.Line 35 adds the new row to the Rows collection of the Students table of the dataSet.Now all that is left is to submit the changes to the database. Inside a try block, we called the DbAdapter.Update() method and passed the dataSet and the name of the DataTable that contains the updated results. By calling this method, the corresponding INSERT statement is generated by CommandBuilder and then it is executed to the database. It returns an integer which indicates the number of rows that were successfully updated. We check its values in line 41 to determine if the insertion is successfull. Lines 51-52 reverts the textboxes and the buttons to their previous states and we switch back the insertReady flag to false. The buttonEdit also acts as a toggle button and most of the code is similar to the code of buttonAddNew. 1 private void buttonEdit_Click(object sender, EventArgs e) 2 { 3 if (!updateReady) 4 { 5 buttonEdit.Text = "Update"; 6 textBoxStudentID.Enabled = false; 7 textBoxFirstName.Enabled = true; 8 textBoxLastName.Enabled = true; 9 textBoxGender.Enabled = true; 10 textBoxAge.Enabled = true; 11 textBoxAddress.Enabled = true; 12 buttonShow.Enabled = false;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62}

buttonAddNew.Enabled = false; buttonDelete.Enabled = false; updateReady = true; } else { buttonEdit.Text = "Edit"; command.CommandText = "SELECT * FROM Students"; dataSet.Tables.Clear(); adapter.Fill(dataSet, "Students"); foreach (DataRow student in dataSet.Tables["Students"].Rows) { if (student["StudentID"].ToString() == textBoxStudentID.Text) { student["FirstName"] = textBoxFirstName.Text; student["LastName"] = textBoxLastName.Text; student["Gender"] = textBoxGender.Text; student["Age"] = textBoxAge.Text; student["Address"] = textBoxAddress.Text; } } try { int result = adapter.Update(dataSet, "Students"); if (result > 0) MessageBox.Show("Update successful."); else MessageBox.Show("Failed to update."); } catch (SqlException ex) { MessageBox.Show(ex.Message); } textBoxStudentID.Enabled = true; textBoxFirstName.Enabled = false; textBoxLastName.Enabled = false; textBoxGender.Enabled = false; textBoxAge.Enabled = false; textBoxAddress.Enabled = false; buttonShow.Enabled = true; buttonAddNew.Enabled = true; buttonDelete.Enabled = true; updateReady = false; }

Example 6 Clicking the buttonEdit for the first time will enable the text boxes and disable the buttons except the buttonEdit itself. We used the updateReady field to make the button toggle its functionality.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

After the changes has been made to the current student, clicking the button the second time will send the changes to the database. Lines 25-35 searches the student with the StudentID indicated in the textBoxStudentID. We did this using a foreach loop and we retrieve every row from the Students table of the dataSet. If the current retrieve row has a StudentID equal to the one in the textbox, then we update every field to whatever new value typed by the user in the text boxes. Finally, the buttonDelete's Click event handler is shown in Example 7. private void buttonDelete_Click(object sender, EventArgs e) 111111111111111{ 2 command.CommandText = "SELECT * FROM Students"; 3 dataSet.Tables.Clear(); 4 adapter.Fill(dataSet, "Students"); 5 6 7 foreach (DataRow student in 8 dataSet.Tables["Students"].Rows) 9 { 10 if (student["StudentID"].ToString() == 11 textBoxStudentID.Text) 12 { 13 student.Delete(); 14 break; 15 } 16 } 17 18 try 19 { 20 int result = adapter.Update(dataSet, "Students"); 21 22 if (result > 0) 23 MessageBox.Show("Student successfully deleted."); 24 else 25 MessageBox.Show("Failed to delete student."); 26 } 27 catch (SqlException ex) 28 { 29 MessageBox.Show(ex.Message); 30 } 31 32 command.CommandText = "SELECT * FROM Students"; 33 adapter.Fill(dataSet, "Students"); }

Example 7 The code for deleting a row is simillar to updating in which we simply used a foreach loop to find the student to delete. If the row has a StudentID equal to the one indicated in the textBoxStudentID, then line 12 deletes that row using the Delete() method. We then exit the loop by using the break statement. Our simple enrollment system is now complete. To test it, run the program and type an existing StudentID in the first text box. Click the show button to see the student's information. If you COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

want to edit those information, you can click the buttonEdit, type the new values, and click buttonEdit again to save the changes. You can also delete that student by clicking buttonDelete. To add or enroll a new student, click the buttonAddNew and type the information of the new student into the fields. Click the buttonAddNew once more to add the student into the Students database table. Download Project: SimpleEnrollmentSystemDisconnected.rar

Connecting to an Access Database You can use the classes in ADO.NET to connect to a Microsoft Access Database. We use the OLE DB data provider and the System.Data.OleDb namespace for an Access database. This tutorial shows you the steps in creating an access database and creating an application that connects to it. We will be using Microsoft Access 2007 version of Access. Open Access 2007, and in the home screen, click the Blank Database Icon. On the right side, you will be prompted to name the new database and indicate the location to where the database will be located. Name your database Members.accdb and you can choose any location you want, but for the sake of simplicity, this tutorial will place the file in the C:\ root directory. Click the Create button and you will be brought to Access' Datasheet View with a new table. You can start adding columns here, but it is easier to switch to Design View and add the columns/fields there so in the ribbon, click View and then Design View. Access will prompt you to name your table, name it Members. Once you are in the Design view, you can now add each fields. The default field you will see is the ID field and the data type is AutoNumber. Data types indicate the type of data that the field will store. You will also notice a key beside it. It means that this field will serve as the primary key. Primary key simply means that values in this field should be unique. The AutoNumber data type means that this field will be automatically filled by access as new records are added. An optional column, Description, simply shows the use of a certain field. You can leave it blank or add a usefull description about the purpose of the field. Now add the following fields to our table. Field Name Data Type FirstName Text LastName Text Age Number The Text data type indicates that the field is expected to hold a string or text while the Number data type holds numeric data (integers and floating-points). Once you added the fields, return to Datasheet View by going to View > DataSheet View. If you are prompted to save the table, do so. Add the following values to their respective fields. Note that the ID field will automatically be filled by Access. FirstName LastName Age COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

FirstName LastName Age John Smith 21 Mark Mayer 23 Alvin Minsky 27 Vince Roster 22 Ben Marcus 18 Ellise Fisher 25 Now that we have some records in our database, we can now create an Application that connects and gets the data from this database. But first, close Microsoft Access 2007 and be sure to save the data.

Querying Data From an Access Database In this lesson, we create a simple form that queries and shows data of individual record from the Access database created in the last lesson. Open Visual Studio and create a new Windows Application. Name the project AccessConnection. Add three labels and three textboxes. Change the Text property of the labels to First Name, Last Name, and Age. Change the Name property of the TextBoxes to txtFirstName, txtLastName, and txtAge respectively. Add four buttons and change their text to First, Prev, Next, and Last. Change their Name property to btnFirst, btnPrev, btnNext, and btnLast. Your form should look like this:

Double click the actual form to generate an event handler for the form's Load event. The load event will contain the code that queries the values to the database and show the field values of the first record to their respective text boxes. 1 2 3 4

using using using using

System; System.Windows.Forms; System.Data; System.Data.OleDb;

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

5 6 namespace AccessConnection 7 { 8 public partial class Form1 : Form 9 { 10 private OleDbConnection connection; 11 private OleDbCommand command; 12 private OleDbDataAdapter adapter; 13 private DataSet dataset; 14 private string firstname; 15 private string lastname; 16 private int age; 17 private int position; 18 19 public Form1() 20 { 21 InitializeComponent(); 22 } 23 24 private void Form1_Load(object sender, EventArgs e) 25 { 26 connection = new OleDbConnection(); 27 command = new OleDbCommand(); 28 adapter = new OleDbDataAdapter(); 29 dataset = new DataSet(); 30 31 connection.ConnectionString = 32 @"Provider=Microsoft.ACE.OLEDB.12.0;Data 33Source=C:\Members.accdb;" + 34 "Persist Security Info=False"; 35 36 command.Connection = connection; 37 command.CommandText = "SELECT * FROM Members"; 38 39 adapter.SelectCommand = command; 40 41 try 42 { 43 adapter.Fill(dataset, "Members"); 44 } 45 catch (OleDbException) 46 { 47 MessageBox.Show("Error occured while connecting to 48database."); 49 Application.Exit(); 50 } 51 52 ShowValuesOfRow(0); 53 } 54 55 private void ShowValuesOfRow(int pos) 56 { 57 DataRow row = dataset.Tables["Members"].Rows[pos]; 58 position = pos; 59 60 firstname = row["FirstName"].ToString(); 61 lastname = row["LastName"].ToString();

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

62 63 64 65 66 67

age = (int)row["Age"]; txtFirstName.Text = firstname; txtLastName.Text = lastname; txtAge.Text = age.ToString(); } } }

Example 1 Notice that we use the System.Data.OleDb namespace. This namespace contains the classes that we will be needing to connect to our Access Database. The namespace System.Data contains the DataSet class which will holds the data retrieved from the database. We declared objects for the OleDbConnection (used for connecting to database), OleDbCommand (handles the sql command), OleDbDataAdapter (used to communicate to the database and retrive its values), the DataSet, and some fields to hold the values from the database. The position field will be used to monitor which record to show in the textbox. Inside the Load event handler of the Form, we initialized the objects neccessary to connect to the data source. We then set the ConnectionString property of the OleDbConnection class to the connection string of Access 2007. The connection string parameter Data Source specifies the path of the Access 2007 file in your system. We connect the OleDbConnection instance to the OleDbCommand through its Connection property. We also specified the SQL command through its CommandText property. The SQL command specifies the we should get all the rows and fields from the Members table. We set the SelectCommand property of the OleDbDataAdapter instance. We used the OleDbDataAdapter.Fill() method that executes the command in the SelectCommand property and put the data into the dataset with the specified table name. Enclosing the Fill() method in a try..catch handles any exception that might occur. We called the ShowValuesOfRow() method to show the values of the specified row or index. We passed 0 as an argument to show the values of the first row. Inside the method, we retrieve the specified row by accessing the Rows property of the Tables property of the DataSet object. We passed the name of the table(in this case "Members") as the key to the Tables property and the value of pos parameter as the index of the Rows property to get a specific row from the Members table. The result is stored to a DataRow object which represents a single row in a DataTable. The position is then adjusted. The values of each columns of the retrieved row is placed to their respective fields and the fields are placed to their respective text boxes. When you run the program, the form should display the first record.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Let's add functionality to the four buttons. Lets start with btnFirst. Double click the button the add an event handler to its Click event. private void btnFirst_Click(object sender, EventArgs e) { ShowValuesOfRow(0); }

Example 2 The code simply calls the ShowValuesOfRow() method and passes 0 as an argument to display the first row. Double click btnLast and add the following code. private void btnLast_Click(object sender, EventArgs e) { int lastIndex = dataset.Tables["Members"].Rows.Count - 1; ShowValuesOfRow(lastIndex); }

Example 3 The first line determines the index of the last record from the Members table. We called the ShowValuesOfRow() method and passed the last index to the method to display the last row's data. Double click the btnPrev button and add the following code. private void btnPrev_Click(object sender, EventArgs e) { if (position > 0) { position--; ShowValuesOfRow(position); }

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

}

Example 4 We first check if the position is greater than 0. This will prevent the program from querying a row located at an invalid index such as -1. Inside the if structure, we decrement the position and called the ShowValuesOfRow() passing the new position as the argument. Double click the btnNext button and add the following code. private void btnNext_Click(object sender, EventArgs e) { int lastIndex = dataset.Tables["Members"].Rows.Count - 1; if (position < lastIndex) { position++; ShowValuesOfRow(position); } }

Example 5 We retrieve the last index of the rows and check if the position is less than the last index. This is also to prevent the program on retrieving an invalid index that will cause an IndexOutOfRange exception to be thrown. The position is incremented by 1 and the values of the new row is displayed. Now run the program. Clicking the First button displays the first record. Clicking the Last button displays the last record. Clicking the prev and next buttons will display the previous and next records. We can use the codes in this lesson to connect to an SQL Data Source. All we need to do is change the type of Provider. You also need to change the connection string to an SQL Server connection string.

Code to navigate between records If you debugged your code you'll know the error. But first thing you should modify this 1. string cs = "user id=scott;password=tiger"; 2. cn = new OracleConnection(cs); 3. cn.Open(); 4. // MessageBox.Show("Oracle connection opened sucessfully"); 5. OracleDataAdapter da = null; 6. OracleCommandBuilder cmb = null; 7. da = new OracleDataAdapter("select * from dept", cn);

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

8. cmb = new OracleCommandBuilder(da); 9. ds = new DataSet(); 10. da.Fill(ds, "deptx"); 11. Rec_Max = ds.Tables["deptx"].Rows.Count; 12. NavigateRecords(inc); 13. cn.Close(); 14. cn.Dispose();

to 1. if(!Page.IsPostBack) 2. { 3. string cs = "user id=scott;password=tiger"; 4. cn = new OracleConnection(cs); 5. cn.Open(); 6. // MessageBox.Show("Oracle connection opened sucessfully"); 7. OracleDataAdapter da = null; 8. OracleCommandBuilder cmb = null; 9. da = new OracleDataAdapter("select * from dept", cn); 10. cmb = new OracleCommandBuilder(da); 11. ds = new DataSet(); 12. da.Fill(ds, "deptx"); 13. Rec_Max = ds.Tables["deptx"].Rows.Count; 14. NavigateRecords(inc); 15. cn.Close(); 16. cn.Dispose(); 17. }

“MORE TUTORIALS COMING SOON”

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

REFERENCE List of Reserved Keywords The C# language has many reserved keywords that you cannot use as identifiers. The following is the full list of those reserved key words: abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void volatile while The following are contextual keywords that are only treated as keywords at special events and locations. add alias ascending by descending equals from get global group into join let on orderby partial remove select set value var where yield

Operator Precedence Chart Operator precedence determines which operators and expressions should be caculated first. The following is the full operator precedence chart of C#. Operators in the same row have the same

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

precedence. The associativity determines how to evaluate expressions having multiple operators with the same level of precedence. Operator Type Associativity . member access () method call [] element access ++ postfix increment -postfix decrement left-to-right new object creation typeof get the type of object sizeof get the size in bytes of a type checked checked evaluation unchecked unchecked evaluation + unary plus unary minus ! logical negation ~ bitwise not operator right-to-left ++ prefix increment -prefix decrement (type) casting * multiplication / division left-to-right % modulus/remainder + addition subtraction left-to-right > right shift operator < less than > greater than = greater than or equal to is type comparison as type conversion != is not equal to left-to-right == is equal to & bitwise AND left-to-right ^ bitwise XOR left-to-right | bitwise OR left-to-right && logical AND left-to-right || logical OR left-to-right ?? null coalescing right-to-left ?: conditional right-to-left

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Operator = *= /= %= += -= = &= ^= |=

Type assignment multiplication assignment division assignment modulus assignment addition assignment subtraction assignment left shift assignment right shift assignment bitwise AND assignment bitwise XOR assignment bitwise OR assignment

Associativity

right-to-left

Casing Styles in .NET Three capitalization styles are used in C# and .NET. The PascalCasing , camelCasing and UPPERCASE. Pascal Casing starts with a capital letter followed by small letters. All succeeding words in Pascal Casing should also start with capital letters. Examples are TheNumber, MyCar, AnimalFarm. Camel Casing is simillar to Pascal Casing only that it starts its name with a small letter. Examples are theNumber, myCar, animalFarm. Uppercase means every character is written in uppercase such as PI or PRICE. Pascal Casing is used for: 



 



Methods. All the methods in the .NET Framework are named using the Pascal Casing. If you are creating methods, use Pascal Casing as well. Although there is one exception. When naming event handlers for controls on a form in C#, the method usually starts with the name of the control (which starts with lower case) followed by an underscore and then the name of the event. Property. When naming a property, we usually follow the name of the private data member it references. For example, if you have a member called myName, we name the corresponding property with MyName. Class. Classes are also named using Pascal Casing. It is apparent on all the classes of the .NET Framework. Interface. When naming an interface, always precede it with a capital I followed by the name of the interface starting also with a capital letter. For example, If I want to make an interface named Clickable, I will name it IClickable. Namespaces. When you write your namespace, you should use Pascal Casing as well.

Camel Casing is used for:   

Fields Method Variables Names of Controls in Windows Forms

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN



Method Parameters

Uppercase is used when writing constants.

Decimal to Binary Conversion Binary numbers in the computer world are often grouped by 8 digits or bits to form 1 byte. To start converting a decimal number to binary, the first step is to reserve 8 blank slots and we will put binary numbers on each slot as we progress. Suppose that we want to convert the number 54 to binary:

Now, we need to remember a simple sequence. Binaries are base 2, so we use 2 as a base and raise it to a power starting with 0.

By getting the answer for each 1, we get the following.

Notice that we start with 1 and the next one is double its value which is 2. The following ones are just doubled values of their preceding values. With this values we can now get the binary equivalent of our decimal number. To start, find the highest number that does not exceed our current value whic is 54. In this case, 32. We place a 1 in the position where the 32 is located.

We now subtract 32 from 54 (54 - 32 = 22). Our current value is now 22. Repeat the step of finding the highest value that does not exceed our current value which is 22. The number 16 qualifies our condition so again, place a 1 where 16 is located.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

We then subtract 16 from 22 (22 - 16 = 6) making 6 our new current value. Find the largest number in the sequence that does not exceed six. 8 exceeds 6, so we should use 4 and place again a 1 in its position.

We subtract 4 from 6 (6 - 4 = 2) and we find the value that does not exceed our new current value 2. There's only one number in the sequence that does not exceed 2, and thats 2 itself. So place again 1 in its position. Subtracting 2 from our current value 2 results to 0. This time, we can now stop adding 1's.

The final process is placing 0's on all blank spaces.

We finally arrived to the binary equivalent of 54 which is 00110110. We can omit the leading 0's and write 110110 as the binary equivalent of 54. Please note that higher numbers require more bits (slots) for conversions. How can we know if a number fits 8 bits. Simply double the last number which is 128 and we get 256. All the number below 256 can be converted using 8 bits. If a decimal to convert is 256 or higher, then we need to add more bits when converting. For example, if we want to convert 312, then we will be needing 9 bits.

The value of the 9th bit is 28 or 256 which is simply a doubled value of its previous bit which is 128. 9 bits can only contain values below 512 which is twice the value of 256. Again, if you have a value equal or greater than 512, then you need to add again 1 more bits.

Binary to Decimal Conversion Converting from binary to decimal is easy. You first need to know the positional values of each bit. Suppose we have a binary number 10100111 that we need to convert to decimal.

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

Positional values starts from 20 which is 1 to 2n-1 where n is the number of bits or digits. Since we have 8 bits, the last positional value is 28-1 = 27 = 128. We write the positional values from right to left. Once we have determined the positional values, we simply add all the positional values that has 1 as its bit.

We now arrived at 167 as the final decimal answer for our binary number 10100111.

Converting Negative Numbers to Binary Converting negative numbers to binary is not simple and can be confusing. C# and .NET uses Two's Complement Notation. To show how the Two's Complement Notation works, let's convert -7 to its binary equivalent. Suppose that -7 has given a type of int so it has 32-bits (32 binary digits). int value = -7;

The first step is to convert a negative value to its positive value so -7 becomes +7 or simple 7. We then convert 7 to its binary representation. 7 = 00000000000000000000000000000111

The value 7 is equivalent to 111 in binary but assuming that we stored the value in an int variable, then it will have 32-bits that's why we add leading 0's to fill all 32 slots. After converting the negative number's positive equivalent to binary, we use one's complement to each bits. In C#, this is equivalent to using the bitwise NOT operator (~). Doing this operation simply reverses the value of each digit. So the binary representation of 7 when one's complement is used will become: ~7 = 11111111111111111111111111111000

To perform two's complement, simply add one the the new binary value. 11111111111111111111111111111000 + 00000000000000000000000000000001 ---------------------------------11111111111111111111111111111001

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN

The result is the binary representation of -7. At first look, it won't seem like it realy is negative 7. That's why I said earlier that it can be confusing. I mean, if you will convert the final binary result to decimal using the techniques we have learned, you will arrive at value 4,294,967,289. But C# and .NET uses the leftmost bit as an indication of whether a number is positive or negative. It means, that if the leftmost bit is 1, then the number is considered negative, if it is 0, the number is considered positive. Therefore, when using int as the type, the 32nd bit is not included when calculating a values decimal value. After all 4,294,967,289 will not fit in an int variable. You should use long or uint instead. To prove that the final binary result is really -7. We can add it to the binary value of 7. The result should be 0 (-7 + 7 = 0). 11111111111111111111111111111001 + 00000000000000000000000000000111 ---------------------------------00000000000000000000000000000000

If you don't know how to add binaries, the following is the three possible combinations and their results. 1 + 0 = 1 0 + 1 = 1 1 + 1 = 0 carry 1

Since the first pair of digit is both 1, the first digit of the answer is 0 and 1 is carry over to the next column and so on until we reach the final column. In the final column there should still be one being carried over from the last column so the result is still 0 and we discard the 1 to be carried.

“MORE TUTORIALS COMING SOON”

COMPILED BY:

Bsc ABDULRAHIM ALI ATHUMAN