Module-3 With Content

Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

Programming using C# .

NET [18MCA51, 16/17MCA52]


Module – 3: Delegates, Events, Exception Handling and ADO.NET

Chapter – 1: Delegates and Events


1.1 Delegates
1.2 Creating and using Delegates
1.3 Muticasting with Delegates
1.4 Events
1.5 Event Sources and Event Handlers
1.6 Events and Delegates
1.7 Multiple Event Handlers

Chapter - 2: Exception Handling


2.1 Introduction
2.2 The try/catch/throw/ finally statement
2.3 Custom Exception
2.4 System.Exception
2.5 Handling Multiple Exception
Chapter - 3: Data Access with ADO.NET
3.1 Understanding ADO.NET
3.2 Describing the Architecture of ADO.NET
3.3 ADO.NET Entity Framework
3.4 Creating Connection Strings
3.5 Creating a Command Object
3.6 Working with DataAdapters
3.7 Using DataReader

Prepared by
Mrs. Suma M G
Assistant Professor
Department of MCA
RNSIT
Bengaluru – 98.
Programming using C# Module - 3 Chapter – 1: Delegates and Events
Chapter -1

Delegates and Events

1.1 Delegates:
A delegate is special type of object that contains the details of a method rather than data.
OR
A delegate is a class type object, which is used to invoke a method that has been encapsulated into it at the
time of its creation.
• A delegate is a reference type variable that holds the references to a method of any class.
• Delegates are especially used for implementing events and the call-back methods.
• All delegates are implicitly derived from the System.Delegate class.

Uses:
Suppose you need to create a program that requires data, such as student information, to display it on a website.
This data can be retrieved by calling a method without having to know to compiler time which method is to be
invoked. In this case, you need to create an object of delegate and encapsulate a reference to that method
inside the delegate object.

1.2 Creating and using Delegates:


Following are the four steps to create and use a delegate in your program:
i. Declaring a delegate iii. Creating delegate objects
ii. Defining delegate methods iv. Invoking delegate objects

i. Declaring a delegate:
A delegate represents a class type, it can be declared at any place where a class can be defined – outside all
classes or inside a class.
Syntax: Access-modifier delegate <return-type>
delegate_name(arg1, arg2, … argn);
Where,
Access-modifier –that controls the accessibility of the delegate and can be public, private, protected or internal.
delegate – is a keyword indicates the declaration belongs to a delegate
return-type – return type of the delegate delegate-name – is the name of the delegate
Parameter-list – the list of parameter that the delegate takes.
Example: public delegate void Compute(int x, int y);

ii. Defining delegate methods:


A delegate method is any method whose signature matches the delegate signature exactly. It can be either static
or an instance method.
Example: public static void add(int x, inty){ Define a static method, named
Console.WriteLine(“Sum= {0}”, a+b); add() to be encapsulated into the
} Compute delegate as follows:

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 1 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
Define a instance method, named
public void subtract(int x, inty){
subtract() to be encapsulated into
Console.WriteLine(“Subtract= {0}”, a-b);
the Compute delegate as follows:
}
iii. Creating delegate objects:
Anyone can create an object of a delegate using the following syntax:
Delegate-name object-name = new Delegate-name(expression);
Where,
delegate-name: name of the delegate declared object-name: name of the delegate object
expression: what you want to encapsulate into the delegate object and it can be name of the method or instance
of the delegate type.
Example:
delegate object type is created to hold Compute cmp1 = new Compute(MyDelegate.add);
reference of static add() method.

MyDelegte mdt= new MyDelegate(); delegate object type is created to hold


Compute cmp2 = new Compute(mdt.subtract); reference of instance subtract() method.

iv. Creating delegate objects:


A delegate object is invoked as a method is invoked. delegate-object(argument-list);
Where, delegate-object – the name of the object being invoked;
argument-list – is the list of values that is assigned to the parameters of the method, encapsulated
into the delegate object.
Example: cmp1(2,5); cmp2(5,2);
Example 1.1:

DelegatesDemo.cs
using System;
public delegate int Operation(int p, int q);
namespace Class_Demo{
class DelegatesDemo{
public static int AddNum(int p, int q){ return (p+q); }
public int MultNum(int p, int q){ return (p*q); }
static void Main(){
Operation op1 = new Operation(AddNum);
Console.WriteLine("Value of Num1: {0}", op1(10,20));
DelegatesDemo dd = new DelegatesDemo();
Operation op2 = new Operation(dd.MultNum);
Console.WriteLine("Value of Num2: {0}", op2(5,2));
Console.ReadKey();
} } }

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 2 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
1.3 Multicasting with Delegates:
A delegate object to hold references of and invoke multiple methods. Such objects are called multicast delegates
or combinable delegates. sample s1=new sample(m.add);
You can encapsulate more than one method into a single s1 += m.sub;
delegate object using the overloaded += operator. s1 += m.mul;

Delegate object satisfy the following two conditions can be made as multicast delegates:
• The return type of the delegate is void
• None of the parameters of the delegate is an output parameter but a parameter declared using the out
keyword.
Example 1.2: using System;
namespace Class_Demos{
delegate void sample(int a,int b);
class MCDelegates{
void add(int n1, int n2){
Console.WriteLine(n1+ "+" +n2+ "=" + (n1 + n2));
}
void mul(int n1, int n2) {
Console.WriteLine(n1 + "*" + n2 + "=" + (n1 * n2));
}
void sub(int n1, int n2){
Console.WriteLine(n1 + "-" + n2 + "=" + (n1 - n2));
}
static void Main(){
MCDelegates m=new MCDelegates();
sample s1=new sample(m.add);
s1 += m.sub;
s1 += m.mul;
s1(10, 20);
Console.ReadKey();
}
}
}

1.4 Events:
An event is a delegate type class member that is used by an object or a class to provide a notification to other
objects that an event has occurred. The “event” keyword can be used to declare an event.

Syntax: Access-Modifier event type event-name;

Where,
Access-Modifier – that determines the accessibility of the event
event – is a keyword
type – type of event, which should necessarily be a delegate type
event-name – valid c# identifier.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 3 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
❖ You need to define a method to listen and handle the event and then bind this method to the event using
the overloaded += operator as follows.

Class-object⚫event-name += new class-object⚫delegate-name(method-name);

❖ You need to detach from a source of events, you can use −= operator as follows:
Class-object⚫event-name -= new class-object⚫delegate-name(method-name);

Example 1.3: This application, named EventHandlerDemo, where you find a simple event source object.
This object contains a given internal member variable that can be set using a member function. Each time this
member variable is changed, the event source fires an event to notify any listeners that changes are pending. If
no event handlers are defined, the event source notifies about that too.
EventsDemo.cs
using System;
namespace Class_Demos{
class EventTestClass{
int nvalue; //The value to track
public delegate void ValueChangedEventHandler();//Allow a handler for the event
public event ValueChangedEventHandler Changed; //This is the event itself
//This method is used to fire the event
protected virtual void onChanged(){
if (Changed != null)
Changed();
else
Console.WriteLine("Event fired. No handler");
}
public EventTestClass(int nvalue){
SetValue(nvalue);
}
public void SetValue(int nv){
if (nvalue != nv){
nvalue = nv;
onChanged(); //Fire the event
}
}
}
class EventsDemo{
static void Main() {
EventTestClass etc = new EventTestClass(3);
etc.SetValue(5);
etc.SetValue(5);
etc.SetValue(3);
Console.WriteLine("\nPress ENTER to quit...");
Console.ReadLine();
}
}
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 4 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
As you can see, the event handler is called three times. When you call the SetValues method second time,
the event is not fired because the value (which was 5) does not change.

1.5 Event Sources and Event Handler:


When you talk about events, the equation always has two tasks that as follows below.
i. An event source pays attention to firing events and then detects the timing when an event should be fired.
ii. The event handler deals with receiving the information that an event has fired and then verifies the
information that the event is present.
Event Source: Event source is an object that inform other objects or tasks that something has changed.
Notification in C# takes the form of callbacks.
• The event source sends out a general message when it wants to notify other objects about a change, and
then any object interested in the message can read and interpret it.
• The event handling is in the form of publish–and–subscribe, which requires a generalized broadcast
mechanism and that all objects receive all messages.
• Each event source maintains all the events published by it.
• Events are considered to be asynchronous from the perspective of the caller.
• The occurrence of a callback depends upon the event-firing object rather than its caller.

Event handler: receive event notifications. When an event source notifies that an event is called, all the event
handlers that have registered for the notification of that event start executing.
An event handler may be either a static or a non-static method of a class. In case of a static method, event
handlers simply respond to a given event source and take a course of action based on the information passed to
the handler.
Example 1.4:
EventHandlerDemo.cs static void Cat(){
Console.WriteLine("Cat");
using System; }
namespace Class_Demos{
public delegate void EventHandler(); static void Dog(){
class EventHandlerDemo{ Console.WriteLine("Dog");
public static event EventHandler _show; }
static void Main(){
// Add event handlers to Show event. static void Mouse(){
_show += new EventHandler(Dog); Console.WriteLine("Mouse");
_show += new EventHandler(Cat); }
_show += new EventHandler(Mouse); }
_show += new EventHandler(Mouse); }

// Invoke the event.


_show();
Console.Read();
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 5 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
1.6 Events and Delegates:
The entire event mechanism is based around delegates.
A delegate acts as a medium between the event source and the event handler methods. It carries the information
about the event to the event handler and allows it to carry information back to the event handler.
Example 1.5: A simple class contains an event that can be fired. The first two elements you need are the event
itself and a delegate.
using System;
namespace Class_Demos{
class EventHandler{
int nvalue; //The value to track
public delegate void ValueChangedEventHandler();
public event ValueChangedEventHandler Changed;
protected virtual void onChanged(){
if (Changed != null)
Changed();
else
Console.WriteLine("Event fired");
}
public EventHandler(int nvalue){
SetValue(nvalue);
}
public void SetValue(int nv){
if (nvalue != nv){
nvalue = nv;
onChanged(); //Fire the event
}
}
}
class SingleEventHandler{
public void HandleChange() {
Console.WriteLine("Handler called");
}
static void Main(){
EventHandler etc = new EventHandler(3);
SingleEventHandler med = new SingleEventHandler();
etc.Changed += new EventHandler.ValueChangedEventHandler(med.HandleChange);
etc.SetValue(5);
etc.SetValue(5);
etc.SetValue(3);
Console.WriteLine("\nPress ENTER to quit...");
Console.ReadLine();
}
}
}

1.7 Multiple Event Handlers:


Like delegates, events can be multicast. This enables multiple objects to respond to an event notification, you
used the += operator to add the event handler.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 6 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
Example 1.6:
MultiEventDemo.cs
using System;
namespace Class_Demos{
class EventTestClass{
int nvalue; //The value to track
public delegate void ValueChangedEventHandler();
public event ValueChangedEventHandler Changed;
protected virtual void onChanged(){
if (Changed != null)
Changed();
else
Console.WriteLine("Event fired. No handler");
}
public EventTestClass(int nvalue){
SetValue(nvalue);
}
public void SetValue(int nv){
if (nvalue != nv){
nvalue = nv;
onChanged(); //Fire the event
}
else
Console.WriteLine("No Fire");
}
}
class MultiEventDemo{
public void HandleChange1() {
Console.WriteLine("Handler 1 called");
}
public void HandleChange2(){
Console.WriteLine("Handler 2 called");
}
static void Main(){
EventTestClass etc = new EventTestClass(3);
MultiEventDemo med = new MultiEventDemo();
//Create a handler for this class
etc.Changed += new EventTestClass.ValueChangedEventHandler(med.HandleChange1);
etc.Changed+= new EventTestClass.ValueChangedEventHandler(med.HandleChange2);
//event detached from the object
etc.Changed−= new EventTestClass.ValueChangedEventHandler(med.HandleChange2);
etc.SetValue(5);
etc.SetValue(5);
etc.SetValue(3);
Console.WriteLine("\nPress ENTER to quit...");
Console.ReadLine();
}
}
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 7 | 28


Programming using C# Module - 3 Chapter – 1: Delegates and Events
The most interesting part of this application is the OnChanged event, which is highlighted in the code. Notice
that this event source does not know about how many event handlers are defined for this particular event. The
event source simply calls the delegate function. However, when you run the program, you see that both event
handlers are called by the application. This process happens by the internal logic of the delegate mechanism,
which chains together the event handlers behind the scenes.
Another example for single event handler and detach an event from source.
Example1.7:
using System;
namespace Class_Demos{
public delegate string MyDel(string str);
class EventProgram{
event MyDel MyEvent;

public EventProgram(){
this.MyEvent −= new MyDel(this.Welcomeuser);
}
public string Welcomeuser(string username) {
return "Welcome" + username;
}
static void Main(string[] args) {
EventProgram obj1 = new EventProgram();
string result = obj1.MyEvent("C# Class");
Console.WriteLine(result);
Console.ReadLine();
}
}
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 8 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Chapter - 2

Exception Handling
2.1 Introduction:
An exception is a problem that arises during the runtime (execution of a program) such as division of a number
by zero, passing a string to a variable that holds an integer value.
C# exception handling is built upon four keywords: try, catch, finally, and throw.

2.2 The try/catch/throw/finally statement


→ try: A try block identifies a block of code for which particular exceptions is activated. It is followed by
one or more catch blocks.
→ catch: A program catches an exception with an exception handler at the place in a program where you
want to handle the problem. The catch keyword indicates the catching of an exception.
→ finally: The finally block is used to execute a given set of statements, whether an exception is thrown or
not thrown. For example, if you open a file, it must be closed whether an exception is raised or not.
Example 2.1:

ExcepDemo.cs

using System;
namespace Class_Demos{
class ExcepDemo{
static void Main(string[] args){
int div=0, number=10;
try{
div = 100 / number;
}
catch (DivideByZeroException ex){
Console.WriteLine("Exception occured : " +ex.Message);
}
finally{
Console.WriteLine("Result is: {0}", div);
Console.WriteLine("\nPress ENTER to Quit...");
Console.ReadKey();
}
}
}
}

→ throw: A program throws an exception when a problem shows up.


This is done using a throw keyword. The throw statement takes only a single argument to throw the
exception. When a throw statement is encountered, a program terminates.
In the following snippet, we have
try{ throw new DivideByZeroException(); }
thrown a new catch{ Console.WriteLine(“Exception”); }
DivideByZeroException explicitly.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 9 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Example 2.2:
ThrowStat.cs
using System;
namespace Class_Demos{
class ThrowStat{
static void Main(string[] args){
int number;
Console.WriteLine("Enter a number");
number = int.Parse(Console.ReadLine());
try{
if (number > 10)
throw new Exception("OutofSize");
}
catch (Exception ex){
Console.WriteLine("Exception occured : " +ex.Message);
}
finally{
Console.WriteLine("This is last statment");
Console.WriteLine("\nPress ENTER to Quit...");
Console.ReadKey();
}
}
}
}

2.3 Custom Exception(ApplicationException):


The ApplicationException is thrown
public class ApplicationException : Exception{
by a user program, not by the common
//Various constructors.
language runtime. If you are designing
}
an application that needs to create its
own exceptions.
To create your own exception class, here are some important recommendations:
• Give a meaningful name to your Exception class and end it with Exception.
• Throw the most specific exception possible.
• Give meaningful messages.
• Do use InnerExceptions.
• When wrong arguments are passed, throw an ArgumentException or a subclass of it, if necessary.

NOTE: According to the .NET framework documentation, SystemException is meant only for
those exceptions defined by the common language runtime whereas ApplicantionException is
intended to be used by user code.

Building Custom Exceptions, Take One:


Any custom exception we create needs to derive from the System.Exception class. You can either derive
directly from it or use an intermediate exception like SystemException or ApplicationException as base class.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 10 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Like any class,
• You are free to include any number of custom members that can be called within the catch block of the
calling logic. public class TestException: ApplicationException{
• You are also free to override any TestException() {}
virtual members defined by your TestException(string Msg):base(Msg){}
parent classes as shown here. public override string Message(){
get{return “. . . .” ;} }
}
Example 2.3:

using System;
namespace Chapter5_Examples {
class TestException : ApplicationException{
public override string Message{
get{
return "This exception means something bad happened";
}
}
}
class CusException {
static void Main(){
try{
throw new TestException();
}
catch(TestException ex){
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
}

Here, you have defined overridden the Message property to return an exception message to the try block. Then
this message will be caught by the catch block.

Building Custom Exceptions, Take Two:


Set the parent’s Message property via an incoming constructor parameter. Here, you are simply passing the
parameter to the base class constructor.
With this design, a custom exception class is a uniquely named class deriving from
System.ApplicationException.
class MyException : ApplicationException {
public MyException(){ . . . }
public MyException(String Msg): base(Msg){. . . }
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 11 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Example 2.4:
using System;
namespace Chapter5_Examples {
class MyException : ApplicationException {
public MyException(String Msg): base(Msg){
Console.WriteLine("Pass the message up to the base class");
}
}
class CusException1{
static void Main(string[] args){
try{
throw new MyException("This is My Exception");
}
catch(MyException ex){ Console.WriteLine(ex.Message); }
Console.ReadLine();
}
}
}

Building Custom Exceptions, Take Three:


To build a correct and proper custom exception class, which requires to follow the below points:
• Derives from Exception /ApplicationException
• Is marked with the [System.Serializable] attribute
• Defines a default constructor
• Defines a constructor that sets the inherited Message property
• Defines a constructor to handle “InnerExceptions” and the serialization of your type
However, to finalize our examination of building custom exceptions, here is the final iteration of
CustomException:
[Serializable]
public class CustomException : Exception{
public CustomException() : base() { }
public CustomException(string message): base(message) { }

public CustomException(string format, params object[] args)


: base(string.Format(format, args)) { }

public CustomException(string message, Exception


innerException): base(message, innerException) { }

public CustomException(string format, Exception

innerException, params object[] args)


: base(string.Format(format, args), innerException) { }

protected CustomException(SerializationInfo info,


StreamingContext context) : base(info, context) { }
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 12 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Then, how to throw the exception to the above iteration as shown below:

1. Throw exception without message: throw new CustomException()


2. Throw exception with simple message: throw new CustomException(message)
3. Throw exception with message format and parameters
throw new CustomException("Exception with parameter
value '{0}'", param)
4. Throw exception with simple message and inner exception
throw new CustomException(message, innerException)
5. Throw exception with message format and inner exception. Note that, the variable length params are
always floating.
throw new CustomException("Exception with parameter
value '{0}'", innerException, param)
6. The last flavor of custom exception constructor is used during exception serialization/deserialization.

2.4 System.Exception:
System.Exception class represents an error that occurs during runtime of an application. This class is the base
class for all exceptions.
When an error occurs, either the system or the currently executing application reports it by throwing an
exception containing information about the error. Once thrown, an exception is handled by the application or
by the default exception handler.
The Exception class has several properties that make understanding an exception easier. These properties
include:
Table 2.1: Property list of the System.Exception
System.Exception
Meaning
Property
is an IDictionary that can hold arbitrary data in key-value pairs. By default, this
Data
collection is empty.
HelpLink can hold a URL(or URN) to a help describing the error in full detail.
can be used to create and preserve a series of exceptions during exception handling.
InnerException
• use to create a new exception that contains previously caught exceptions.
• The original exception can be captured by the second exception in the
InnerException property, allowing code that handles the second exception to
examine the additional information.
returns the textual description of a given error. The error message itself is set as a
Message
constructor parameter.
Source returns the name of the assembly that threw the exception.
contains a stack trace that can be used to determine where an error occurred. The
StackTrace
stack trace includes the source file name and program line number if debugging
information is available.
returns a MethodBase type, which describes numerous details about the method that
TargetSite
threw the exception.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 13 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Example 2.3:
using System;
namespace Chapter5_Examples{
class EcePrope {
static void Main(){
try { int value = 1 / int.Parse("0"); }
catch (Exception ex){
Console.WriteLine("HelpLink = {0}", ex.HelpLink);
Console.WriteLine("Message = {0}", ex.Message);
Console.WriteLine("Source = {0}", ex.Source);
Console.WriteLine("StackTrace = {0}", ex.StackTrace);
Console.WriteLine("TargetSite = {0}", ex.TargetSite);
Console.ReadKey();
}
} } }

The following table provides some of the predefined exception classes derived from the Sytem.Exception class:

Table 2.2: Predefined classes are inherited from System.Exception

Exception Class Description


AccessException Occurs when a type member, such as a variable, cannot be accessed
ArgumentException Defines an invalid argument to a method
ArgumentNullException Occurs if null argument is passed to a method that does not accept it
ArgumentOutofRangeException Occurs if an argument value is not within a range
ArithmeticException Occurs if an Arithmetic overflow or Arithmetic underflow has occurred
ArrayTypeMismatchException Occurs if you try to store the incorrect type of object in an array
BadImageFormatException Occurs when the image file of a DLL file or an executable program is
invalid
DivideByZeroException Occurs if you try to divide a number by zero
FormatException Occurs if there is an incorrect format of argument
IndexOutOfRangeException Occurs if the index of an array is out of bond
InvalidCastExpression Occurs if you try to cat an object to an invalid class
InvalidOperationException Occurs if a method call is invalid for the current state of the object
MissingMemberException Occurs if you try to dynamically access a member of a class that does
not exist
NotFiniteNumberException Occurs if a number is invalid or infinite
NotSupportedException Occurs when a method that is invoked is not supported
NullReferenceException Occurs if you try to make use of an unassigned reference
OutOfMemoryException Occurs if an execution stops due to lack of memory
StackOverflowException Occurs if a stack overflow

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 14 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
2.5 Handling Multiple Exception:
In some cases, more than one exception could be raise by a single piece of code. To handle this type of situation,
you can specify two or more catch block, each having a different type to handle various exceptions.
• When an exception is thrown, each catch block is checked in turn to see if the exception thrown is the
same type as, or derives from, that declared in the catch statement.
• When a match is found, the code within the catch block is executed. Only one catch block’s code is ever
executed.
• Exceptions thrown that do not match any of the declared types remain unhandled.
Example 2.4:

using System;
namespace Chapter5_Examples{
class MultCatch{
static void Main(){
int a = 1;
try{
int b = 77 / a;
int[] arr = {1,2};
arr[4]=100;
}
catch (DivideByZeroException ex){
Console.WriteLine("Cannot be divide: {0}", ex);
}
catch (IndexOutOfRangeException ex){
Console.WriteLine("Index out of Range:{0}",ex);
}
catch (Exception ex){
Console.WriteLine("Error: {0}", ex);
}
Console.ReadKey();
}
}
}

NOTE: When you are handling multiple catch blocks, you must be aware that when an exception
is own, it will be processed by the “first available” catch.

When you use multiple catch statements, it is important to remember that the exception subclass must come
before any of their super classes. This is because a catch statement that uses a super class will catch exceptions
of that type plus any of it subclasses.

To illustrate exactly what the “first available” catch means, assume you retrofitted the previous logic as
follows:

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 15 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Example 2.5:

using System;
namespace Chapter5_Examples{
class MultCatch{
static void Main(){
int a = 1;
try{
int b = 77 / a;
int[] arr = { 1, 2 };
arr[4] = 100;
}
catch (Exception ex){
Console.WriteLine("Error: {0}", ex);
}
catch (DivideByZeroException ex){
Console.WriteLine("Cannot be divide: {0}", ex);
}
catch (IndexOutOfRangeException ex){
Console.WriteLine("Index out of Range:{0}",ex);
}
Console.ReadKey();
}
}
}

Here, it gives a compile-time error message because,


• A first catch block already catches all exceptions "System.Exception".
• Since DivideByZeroException is a subclass of System.Exception, the first catch statement will handle all
Exception-based errors including DivideByZeroException. So that second catch statement will never
execute.

Checked and Unchecked Statements:


“checked” and “unchecked” statements are used to check the memory overflow exceptions.
 The “checked” keyword is used to check the overflow for integral-type arithmetic operations and
conversions. Overflow occurs when the value of a variable exceeds the required original length of the
variable.

 The “unchecked” keyword ignores the overflow-checking of the integral-type arithmetic operations
and conversions. Arithmetic overflow is ignored, and the program displays the truncated integers from
the result.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 16 | 28


Programming using C# Module - 3 Chapter – 2: Exception Handling
Example 2.6:
using System;

namespace Class_Demos{
class CheckUnDemo{
static void Main()
{
byte num1, num2, result;
num1 = 127;
num2 = 127;
try {
result=unchecked((byte)(num1 * num2));
Console.WriteLine("Unchecked result:" + result);

result=checked((byte)(num1 * num2));
Console.WriteLine("Checked result:" + result);
}
catch(OverflowException ex)
{
Console.WriteLine("Exception occured:" + ex.Message);
}
finally{
Console.WriteLine("Press Enter to Quit...");
Console.ReadLine();
}
}
}
}

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 17 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
Chapter - 3

Data Access with ADO.NET

Introduction:
ADO.NET stands for ActiveX Data Objects and is part of the .NET framework technology that allows to
access and modify data from different data sources. It supports many types of data sources such as Microsoft
SQL Server, MySQL, Oracle, and Microsoft 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.
Various Connection Architectures: There are the following two types of connection architectures:
• Connected architecture: the application remains connected with the database throughout the
processing.
• Disconnected architecture: the application automatically connects/disconnects during the processing.
The application uses temporary data on the application side called a DataSet.

3.1 Understanding ADO.NET:


ADO.NET is the data access and manipulation protocol used by C#, which is used to work with data that is
stored in structured data sources, such as databases and XML files.
The following are some of the important and integral part of ADO.NET:
• Contains a number of classes that provide you with various methods and attributes to manage the
communication between your application and data source.
• Provides a rich set of features, such as connection and commands that can be used to develop robust and
highly efficient data services in .NET applications.
• Provides various data providers that are specific to databases produced by various vendors.
For example, ADO.NET has a separate provider to access data from Oracle databases; whereas, another
provider is used to access data from SQL databases.
• Enables to access different data sources, such as Microsoft SQL Server, and XML, as per your
requirements.
• The ADO.NET classes are found in System.Data.dll and are integrated with the XML classes found in
System.Xml.dll

Some of the important features of ADO.NET are as follows:


→ LINQ:
Stands for Language Integrated Query. Integrated into various aspects of data access in a .NET
framework which includes Dataset disconnected programming model and the existing SQL Server
database schemas.
LINQ to ADO.NET consist of two separate technologies that are
➢ LINQ to DataSet: provides better querying over DataSet.
➢ LINQ to SQL: enables you to directly query SQL Server databases.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 18 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
→ LINQ to DataSet:
✓ Allows to implement LINQ queries for disconnected data stored in a dataSet.
✓ Enables query data that is cached in a DataSet object.
✓ DataSet objects allow to use a copy of the data stored in the tables of a database, without actually
getting connected to the database.
→ LINQ to SQL:
✓ Allows to create queries for data stored in SQL server database in your .NET application.
✓ Can use to translate a query into a SQL query and then use it to retrieve or manipulate data
contained in tables of an SQL Server database.
✓ Supports all the key functions that like to perform while working with SQL, that is, you can
insert, update, and delete information from a table.

3.2 Describing the Architecture of ADO.NET:

Figure 3.1: Showing the ADO.NET Architecture


ADO.NET is a data access technology from Microsoft .Net Framework, which provides communication
between relational and non-relational systems through a common set of components.
ADO.NET consist of a set of Objects that expose data access services to the .NET environment.
ADO.NET is designed to be easy to use, and Visual Studio provides several wizards and other features that can
use to generate ADO.NET data access code.
The two key components of ADO.NET are Data Providers and DataSet.
The .Net Framework includes mainly three Data Providers for ADO.NET. They are
i. Microsoft SQL Server Data Provider ii. OLEDB Data Provider iii. ODBC Data Provider

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 19 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
SQL Server uses the SqlConnection object, OLEDB uses the OleDbConnection Object and ODBC uses
OdbcConnection Object respectively.
The four Objects from the .Net Framework provides the functionality of Data Providers in the ADO.NET.
They are
i. The Connection Object provides physical connection to the Data Source.
ii. The Command Object uses to perform SQL statement or stored procedure to be executed at the Data
Source.
iii. The DataReader Object is a stream-based, forward-only, read-only retrieval of query results from the
Data Source, which do not update the data.
iv. The DataAdapter Object, which populate a Dataset Object with results from a Data Source

DataSet provides a disconnected representation of result sets from the Data Source, and it is completely
independent from the Data Source.

Data Provider in ADO.NET


A data provider is a set of related
components that work together to
provide data in an efficient manner. It is
used in ADO.NET for connecting to a
database, executing commands, and
retrieving results.
The results are either processed directly
or manipulated between tiers and
displayed after combining with multiple
sources. The data provider increase
performance without compromising on Figure 3.2: representation of DataProvider
functionality.

Objects of Data Provider:


The Data provider in ADO.NET consists of the following 4 objects:
Table 3.1: List of objects of Data Provider
OBJECT DESCRIPTION
• Creates connection to the data source.
• The base class for all the Connection objects is the DbConnection class.
• The Connection object has the methods for opening and closing connection and
beginning a transaction.
Connection
Provides three types of connection classes:

• SqlConnection object: to connect to Microsoft SQL Server


• OleDbConnection object: to connect to Microsoft Access
• OdbcConnection object: to connect to Oracle
• Executes a command against the data source and retrieve a DataReader or DataSet.
Command
• It also executes the INSERT, UPDATE or DELETE command against the data source.
• The base class for all the Command objects is the DbCommand class.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 20 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET

The Command object is represented by 3 classes:


✓ SqlCommand ✓ OleDbCommand ✓ OdbcCommand
The Command object provides 3 methods that are used to execute commands on the
Command database.

✓ ExecuteNonQuery(): method executes the commands, such as INSERT,


UPDATE and DELET that have no return value.
✓ ExecuteScalar(): method returns a single value from a database query.
✓ ExecuteReader(): returns a result set by way of the DataReader object.
• Provides a forward-only and read-only connected result set.
DataReader • The base class for all DataReader object is the DataReader class.
• The DataReader object cannot be directly instantiated.
• Updates the DataSet with data from the data source.
• The base class for all DataAdapter objects is the DbDataAdapter class.
• The DataAdapter acts as an intermediary for all the communication between the
database and DataSet.
The DataAdapter object provides 2 methods
DataAdapter
✓ Fill(): is used to fill a DataTable or DataSet with data from the database
✓ Update(): commits the changes to the database.
The DataAdapter provides 4 properties that represent the database command:

✓ SelectCommand ✓ InsertCommand ✓ DeleteCommand ✓ UpdateCommand

Data Provider in ADO.NET:


Different types of data providers include in ADO.NET are as follows:

Table 3.2: List of different types of data provider


Data
Description
provider
• Provides access to Microsoft SQL.
• It uses the System.Data.SqlClient namespace and its own protocol to
SQL communicate with the SQL Server.
Server • It performs well when used to access a SQL Server.
• There is no need to add an OLEDB or the ODBC layer to access the data
provider.
• Provides access to data sources exposed by using OLEDB.
OLEDB • It uses the System.Data.OleDb namespace and holds support for both local
and distributed transaction.
• Provides access to data sources exposed by using ODBC.
ODBC • It uses the System.Data.Odbc namespace and holds support for both local
and distributed transaction.
• Provides access to Oracle data source Oracle client connectivity software.
Oracle • It uses the System.Data.Oracledlient namespace and is contained in the
System.Data.OracleClient.dll assembly

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 21 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
DataSet:
DataSet is a very useful in-memory representation of data
and acts as the core of a wide variety of the data based
applications. A DataSet can be considered as a local copy
of the relevant portions of the database. The data in the
DataSet can be manipulated and updated independent of
the database. You can load the data in the DataSet from
any valid source, such as the MicrosoftSQLServer database,
Oracle Database, or Microsoft Access database.

Component of DataSets:
The various components that make up a DataSet are listed
as follow:

Table 3.3: List of various components of DataSet


DataSet
Description
Components
→ Consists of DataRow and DataColumn and stores data in the table row
format.
→ The DataTable is the central object of the ADO.NET library and
DataTable
similar to a table in a database.
→ The maximum number of rows that a DataTable can contain is fixed at
16,777,216.
→ Represents a customized view of DataTable for sorting, filtering,
searching, editing and navigation.
DataView → allows to create a view on a DataTable to see a subset of data based on
a preset condition specified in the RowStateFilter property.
→ used to present a subset of data from the DataTable.
→ Consists of a number of columns that comprise a DataTable.
→ A DataColumn is the essential building block of the DataTable.
DataColumn
→ A DataType property of DataColumn determines the kind of data that a
column holds.
→ Represents a row in the DataTable.
→ use the DataRow object and its properties and methods to retrieve,
evaluate, insert, delete and update the values in the DataTable.
DataRow
→ NewRow() method of the DataTable to create a new DataRow and the
Add() method to add the new DataRow to the DataTable.
→ also delete DataRow using Remove() method.
→ Allows you to specify relations between various tables.
→ used to relate two DataTable objects to each other through DataColumn
DataRelation objects.
→ The relationships are created between matching columns in the parent and
child tables.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 22 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
There are two types in DataSet. They are:
➢ Typed DataSet:
❖ It has a XML schema and derived from the base DataSet class.
❖ It uses the information, such as tables, columns, and properties from the DataSet Designer,
which is stored in an XML Schema(.xsd) file, to generate a new dataset class.
➢ Untyped DataSet:
❖ It has no built – in schema.
❖ It contains tables and columns, but is accessed only as collections.

DataReader:
The DataReader object helps in retrieving the data from a database in a forward-only, read-only mode. The
base class for all the DataReader objects is the DbDataReader class.
The DataReader object is returned as a result of calling the ExecuteReader() method of the Command
object. The DataReader object enables faster retrieval of data from databases and enhances the performance
of .NET applications by providing rapid data access speed. However, it is less preferred as compared to the
DataAdapter object because the DataReader object needs an Open connection till it completes reading
all the rows of the specified table.

3.3 ADO.NET Entity Framework:


ADO.NET Entity Framework 4.0 is introduced in .NET Framework 4.0 and includes the following components:

• EDM (Entity Data Model): EDM consists of three main parts - Conceptual model, Mapping and
Storage model.
➢ Conceptual Model: The conceptual model contains the model classes and their relationships.
This will be independent from your database table design.
➢ Storage Model: Storage model is the database design model which includes tables, views,
stored procedures, and their relationships and keys.
➢ Mapping: Mapping consists of information about how the conceptual model is mapped to the
storage model.
➢ LINQ to Entities: LINQ to Entities is a query language used to write queries against the object model.
It returns entities, which are defined in the conceptual model. You can use your LINQ skills here.
➢ Entity SQL: Entity SQL is another query language just like LINQ to Entities. However, it is a little
more difficult than L2E and the developer will have to learn it separately.
➢ Object Service: Object service is a main entry point for accessing data from the database and to return
it back. Object service is responsible for materialization, which is the process of converting data returned
from an entity client data provider (next layer) to an entity object structure.
➢ Entity Client Data Provider: The main responsibility of this layer is to convert L2E or Entity SQL
queries into a SQL query which is understood by the underlying database. It communicates with the
ADO.Net data provider which in turn sends or retrieves data from the database.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 23 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET

EDM

Figure 3.3: Showing Architecture of ADO.NET Entity Framework

3.4 Creating Connection Strings:


A connection string is a series of name/value pairs separated 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.
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 provide a ConnectionString property that you can use to
specify the connection string for connecting to a database.
Syntax: connection string for connecting to a SQL Server Express data source:
Data Source=.\SQLEXPRESS;Initial Catalog=University; Integrated Security=SSPI;

The following table is the basic connection string parameters that can use when building connection string.
Note that not all parameters are the same for every data source.
Table 3.4: Lists of basic connection string parameters
Parameter Description
• Used only if you want to connect to an attachable database file.
AttachDBFileName
Example: an .mdf file that isn't registered with the database system.
/ InitialFileName
• The full version of SQL Server doesn't support this.
• The length of time (in seconds) to wait for a connection to the server
Connect Timeout / before terminating the attempt and generating an error.
Connection Timeout
• Defaults to 15 seconds and 0 seconds represent an infinite wait.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 24 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET

Data Source / • The server name or network address of the database product to
Server / Address / connect to.
Add / Network
Address • Use localhost for the current computer.
Initial Catalog /
The database the connection will initially use.
Database
Integrated Security / Defaults to false. When set to true or SSPI, the .NET provider attempts
Trusted_Connection to connect to the data source using Windows integrated security.
When set to false (the default), security-sensitive information such as
the password is removed from the ConnectionString property as soon as
Persist Security Info
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.

3.5 Creating a Command Object:


After establishing a connection to a data source, you can execute commands and return results from the data
source using the DbCommand object. Each .NET framework data provider has its own command object that
inherits from the DbCommand object.
Example:
public partial class Form1:Form{
private void Fomr1_Load (Object sender, EventArgs e){
SqlConnection con =new SqlConnection();
String con_str = @"Data Source=.\SQLEXPRESS; AttachDbFilename=
D:\C#Lab2015\Lab1-Studentdatabase\Lab1-Studentdatabase\
StudentDatabase.mdf;Integrated Security=True;User Instance=True";
SqlCommand cmd=new SqlCommand(“Select * from Student”, con);
SqlAdapter adp=new SqlAdapter(cmd);
DataSet ds= new DataSet();
Ds.Fill(ds, “Student”);
comboBox1.DataSource=ds.Tables[“Student”];
comboBox1.DisplayMember = “Studentid”;
comboBox1.ValueMember=”Studentid”;
}
}

3.6 Working with DataAdapters:


A DataAdapters are a set of objects used to exchange data between a data source and DataSet. This means
that DataAdapter is responsible for reading data from a database into a DataSet and writing the changed
data from the DatSet to the database.

The available DataAdapters in a .NET framework are as follows:

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 25 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
Table 3.5: List of DataAdapter class for different providers in .NET

Provider DataAdapter Class Description


SQL Server SqlDataAdapter Works only with SQL Server
Allows you to work with any data source exposed by
OLE DB OleDbDataAdapter
the OLE DB provider.
ODBC OdbcDataAdapter Allow you to access on ODBC data source
ORACLE OracleDataAdapter Works with Oracle database

The DbDataAdapter class provides the following properties and methods.


Table 3.5: List of properties in DataAdapter class

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 used for
InsertCommand
inserting a record.
Specifies the Command object with the SQL command to be used for
SelectCommand
retrieving records.
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
updating a record.

Table 3.6: List of methods in DataAdapter class

Methods Description
AddToBatch Adds a Command object to a batch that will be executed.

ClearBatch Removes all the Command objects from the batch.

ExecuteBatch Excutes the batch of commands.


Executes the SelectCommand property and fills a DataSet that is
Fill
provided.
InitializeBatching Initialize the batching process.

GetFillParameters Gets the parameters of the SelectCommand property.

TerminateBatching Terminates the batching process.


Calls the corresponding INSERT, DELETE, or UPDATE command of
Update this DataAdapter and updates the data source using the specified
commands.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 26 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
3.7 Using DataReader:
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 the System.Data.Common.DbDataReader base class.
You can retrieve the data in windows application by using DataReader instead of DataAdapter. You can
use the ExecuteReader() to retrieve the rows from a data source.
There are different DataReader for different data source.
Table 3.7: List of DataReader class for different providers in .NET
Provider DataReader Class Description
SQL Server SqlDataReader Works only with SQL Server
Allows you to work with any data source exposed by
OLE DB OleDbDataReader
the OLE DB provider.
ODBC OdbcDataReader Allow you to access on ODBC data source
ORACLE OracleDataReader Works with Oracle database

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.
Table 3.8: List of properties in DataReader class
Property Description
FieldCount Specifies the number of columns of the current row or record.
HasRows Specifies whether the current row has at least 1 row.
IsClosed Specifies whether the DbDataReader is closed.
Specifies the number of rows that has been updated, inserted, or
RecordsAffected
deleted.

Table 3.9: List of methods in DataAdapter class


Methods 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 an 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.

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 27 | 28


Programming using C# Module - 3 Chapter – 3: Data Access with ADO.NET
Questions List
Chapter 1 – Delegates and Events
1. What is meant by the .Net delegate type? Explain the concept with example code. 10
2. Describe four steps to create and use a delegate in your program with an example. 10
3. Explain single cast and multicast delegates in C# with examples. 10
4. What are delegates? Explain with code example, the concept of multicasting with delegates. 10
5. What is event? Explain with an example. 8
6. Describe how to implement the multiple events. Give example. 8
7. Write a short notes on:
i. Delegates and events iv. Event handlers
ii. Events v. Event delegates
iii. Event sources
8. How to detach the event from the event source? Give an example. 6
9. Write a C# program to calculate square and addition of number using delegates. 10

Chapter 2 – Exception Handling


1. Explain .NET Exception handling with valid example code. 6
2. Explain exception handling with a sample program to handle multiple exceptions. 8
3. Define Exception. List and explain the statements of the Exception handling 6
4. How to create a custom exception. Explain any one way to creating a custom exception. 7
5. List the constructors of base class System.Exception. 4
6. Write a short notes on:
i. throw ii. finally
7. Write a C# program using try, catch, finally and explain checked and unchecked statements. 10
Chapter 3 – Data Access wit ADO.NET
1. Explain the architecture of ADO.NET with a neat diagram 10
2. Mention and Explain the features of ADO.NET? 4
3. List and explain objects of ADO.NET Data providers. 10
4. What are the benefits of using of ADO.NET in .NET 4.0 ? 8
5. Briefly explain DataAdapter class in ADO.NET. 8
6. What is connection object? Explain the procedure of getting connected to a database and
running the following queries with relevant example:
7
i. Insert record to a table
ii. Delete records from a table.
7. List out difference between fill() and update() in DataAdapter. 6
8. Explain the following:
i. DataAdapters ii. DataSet iii. DataReader
iv. ODBC DataSource v. SqlCommand
9. With a neat diagram, discuss the ADO.NET Entity Framework. 8
10. Mention and explain the different types of DataProvider. 6

Suma M G, AP, Dept. of MCA, RNSIT for updates: https://sites.google.com/view/sumamg-dotnet/ 28 | 28

You might also like