Pages

Monday, December 13, 2010

Dot Net - Delegate

What?

Its an object which allows you to reference a method.Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.

Actualy its like a pointer in C or C++ but delegate is not a pointer in C#, its an object so we can create the insatnce of delegate by using 'new' keyword. And also unlike function pointers in C or C++, delegates are object-oriented, type-safe, and secure.

An interesting and useful property of a delegate is that it does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.

NOTE : Delegates run under the caller's security permissions, not the declarer's permissions.

Why?
  • Giving you maximum flexibility to implement any functionality you want at runtime.
  • The association between delegate and methods referenced by delegate is established in runtime - so, you get flexibility here.
  • Multi-cast: That's to associate a few methods/functions to ONE delegate. Invoking one delegate fires off ALL methods referenced by that one delegate all at once.
  • The use of delegates promotes good separation of functionality between the business layer/anyother layer and the client code. The client code has no knowledge of how logics works in other layer.
How to decide When to use Delegate OR Interface(Method)?

Delegates are useful when:
  • A single method is being called.
  • A class may want to have multiple implementations of the method specification.
  • It is desirable to allow using a static method to implement the specification.
  • An event-like design pattern is desired.
  • The caller has no need to know or obtain the object that the method is defined on.
  • The provider of the implementation wants to "hand out" the implementation of the specification to only a few select components.
  • Easy composition is desired.
Interfaces are useful when:
  • The specification defines a set of related methods that will be called.
  • A class typically implements the specification only once.
  • The caller of the interface wants to cast to or from the interface type to obtain other interfaces or classes.
Step to Implimentation Delegate?

  1. Declaring a delegate   
          public delegate void ProcessBookDelegate(Book book);

                                      Each delegate type describes the number and types of the arguments, and the type of the return value of methods that it can encapsulate.Whenever a new set of argument types or return value type is needed, a new delegate type must be declared.

   2.    Instantiating a delegate  

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
     
Note that once a delegate is created, the method it is associated with never changes — delegate objects are immutable. 

  3.   Calling a delegate   

   delegateObject(argument)


Reference:
http://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx

Friday, December 10, 2010

DotNet - IComparer Interface

What is IComparer?

Its an interface which Exposes a method that compares two objects.This interface is used in conjunction with the Collection.Sort and Array.BinarySearch methods. It provides a way to customize the sort order of a collection. This interface has a method 'Compare' which Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.

Basicaly this interface uses for sorting the collection of custome object by one of their property.


Example : For soting a collection.

public class GenericComparer : IComparer
{
    private String _Property = null;
    private SortOrderEnum _SortOrder = SortOrderEnum.Ascending;
   
    public String SortProperty
    {
        get { return _Property; }
        set { _Property = value; }
    }

    public SortOrderEnum SortOrder
    {
        get { return _SortOrder; }
        set { _SortOrder = value; }
    }

    public int Compare(object x, object y)
    {
        Fruit ing1;
        Fruit ing2;
       
        if (x is Fruit)
            ing1 = (Fruit) x;
        else
            throw new ArgumentException("Object is not of type Fruit");

        if (y is Fruit)
            ing2 = (Fruit) y;
        else
            throw new ArgumentException("Object is not of type Fruit");
       
        if (this.SortOrder.Equals(SortOrderEnum.Ascending))
            return ing1.CompareTo(ing2, this.SortProperty);
        else
            return ing2.CompareTo(ing1, this.SortProperty);
    }
}


The sort order enumeration.

public enum SortOrderEnum
{
    Ascending,
    Descending
}

Now we can use this comparer in our sort method like

public void Sort(String SortBy, SortOrderEnum SortOrder)
{
    GenericComparer comparer = new GenericComparer();
    comparer.SortProperty = SortBy;
    comparer.SortOrder = SortOrder;
    this.InnerList.Sort(comparer);
}

Reference :

http://www.codeproject.com/KB/cs/GenericComparer.aspx

Thursday, December 9, 2010

SQL Server - Transaction Isolation Levels

What is Transaction Isolation?

In database systems, isolation is a property that defines how/when the changes made by one operation become visible to other concurrent operations. Isolation is one of the ACID (Atomicity, Consistency, Isolation, Durability) properties.

In very simple terms Isolation Levels decide “What happens when some data being referred to (for reading or writing) within an incomplete transaction is also being referred to (for reading or writing) from another connection (or user – actually it is called another ‘transaction lock space)".

Why Transaction Isolation Level required?
  • To avoid dirty read.
  • To avoid non repeatable read.
  • To avoid phantom rows read.
  1. Dirty read                 
                       This is when connections outside the transaction space can read the uncommitted data. You don’t want this to happen in most cases. The only reason when you may want to allow this is when you are creating a report which assumes a certain amount of inaccuracy. You think this situation is rare? Not really. Suppose the report compares the current month sale with last month sale and returns a percentage difference. Consider that the report takes 5 minutes to generate. During these 5 minutes, more transactions may be getting added to the sales data. Typically 5 transactions would get added to the sales table. The average transaction value is Rs. 1000. The total sale for the month is typically 30-40 lacs. In such cases, you really don’t need to worry about absolute accuracy. You can intentionally allow dirty reads because the impact is really not significant from a business perspective.

2.  Non-repeatable read

                       Within a transaction, the same data read any number of times should yield consistent results. If it is not same then the reads are ‘non-repeatable’.

3. Phatom Read

                       If you have already read a range of data based upon a key value, another transaction inserts a new row which happens to have a value between this range. The original range which was referred to would now become invalid. This is because a “Phantom row” was added. This is also a major problem.

How to set the Transaction Isolation Level?

SET TRANSACTION ISOLATION LEVEL { READ COMMITTED
| READ UNCOMMITTED
| REPEATABLE READ
| SERIALIZABLE
}


Example :  SET TRANSACTION ISOLATION LEVEL READ COMMITTED

Different Types of Isolation Level?




1. Read Uncommitted

All data which is uncommitted is readable from any connection. This should not be used unless you have a very good reason to do so.

Limitations:
  • Dirty-reads
  • Lost Updates
  • Phantom reads
  • Non-repeatable reads
Advantages:
  • Higher Concurrency

2. Read Committed

Although it is the default, it does not mean that this isolation level is ideal for all transactions. One of the regular tendencies amongst techies is to simply use default values without giving it a second thought! I cannot imagine the number of phantom and non-repeatable reads that must be occurring in the world because someone simply used the ‘default’ value. It is a scary thought to say the least.
This level is obviously more restrictive than the ‘Read Uncommitted’ level.

Limitations:
  • Lower Concurrency than ReadUncommitted
  • Lost Updates
Advantage:
  • Eliminates Dirty Reads
3. Repeatable read

This prevents dirty reads as well as non-repeatable reads. It does not prevent phantom rows. This is more restrictive than Read Committed level. When I say restrictive what does it mean? It means that the chances of other transactions having to wait for this one to finish are INCREASED. Another way of saying this is – Repeatable Read reduces concurrency compared to Read Committed level.
This specifies that transactions cannot read data that has been modified by other transactions but not yet committed and if the current transaction is reading some data then no other transactions can modify that data until the current transaction completes.

Limitations:
  • Lower Concurrency
  • Phantom Reads
Advantage:
  • Eliminates Dirty Reads
  • Eliminates Lost Updates
  • Eliminates Non-Repeatable Reads
4. Snap Shot

 It specifies that the data accessed by any transaction is consistent and valid for that particular transaction and the data will be same throughout the whole transaction. It implements Row Versioning to isolate data for each transaction i.e. it will keep separate version of each modified row in the transaction in the tempdb database totally dedicated to that transaction. Any update of data in the original row will not affect the current transaction.

Limitations:
  • Low performance due to versioning in tempdb
Advantage:
  • Eliminates Dirty Reads
  • Eliminates Lost Updates
  • Eliminates Non-Repeatable Reads
  • Allows multiple updates by versioning
5. SERIALIZABLE Isolation Level

It is highest level in Isolation levels as a result the concurrency rate is low. But it eliminates all issues related to concurrency like dirty read, non repeatable reads, lost updates and even phantom reads. According to this Isolation Level:
  1. Statements cannot read data if other transactions are performing update operations on the data and is not committed yet.
  2. Also no other transactions can perform any update operations until the current transaction completes its read operations.
  3. And the important point here is that it is performing a Range Lock based on the filters used to get the data from the table i.e. it locks not only the current records but also the new records that are falling under the current filter condition. In simple language, no other transactions can insert new rows that are falling under the current filter condition until the transaction completes.                  
Limitations:
  • Lower Concurrency
Advantage:
  • Eliminates Dirty Reads
  • Eliminates Lost Updates
  • Eliminates Non-Repeatable Reads
  • Eliminates Phantom Reads



Reference
http://www.sqllion.com/2009/07/transaction-isolation-levels-in-sql-server/

Reflection - Load Unreferenced Assemblies at runtime

Reflection

The dictionary meaning of the word ‘Reflection’ is ‘to look back to itself’. This is exactly what is meant by the term reflection in programming world. Reflection is an ability of application to look into the structure of itself. Using the reflection technology, we can retrieve the information about the contents of an assembly (constituting classes and interfaces).


Similarly we can drill down to get the members of these types like fields, methods, and properties. Not only this, but we can also instantiate these types and invoke the methods on these. We can even prepare, compile, and load assemblies at runtime.


Another advantage of  Reflection is it allows you to load assemblies on the fly and treat them as if they were part of your application.Typically this can be used to extend your application after it is released to customers.


For instance we use this feature to add additional reports to customers other than the standard reports that ship with the application, with out having to alter any base app code and with out having to perform any patches. Each of our report file is a .net class, the standard reports are compiled with in the Main assembly and if the customer requests for different sets of reports, we write those class files compile them to an assembly and drop in our app bin folder. Thatz all we need to do, the reflection code in the app will take care of the rest.




To demonstrate this, let's setup a hypothetical situation in which we have an application, and a .NET DLL unreferenced by our application whose types we need to access at runtime. The DLL will be called MyDLL.dll, and the application will be called MyApp.exe. How would we view the types contained inside MyDLL from MyApp at runtime when MyDLL isn't referenced by MyApp? The System.Runtime.Assembly class can be used to access MyDLL in the following manner:


System.Reflection.Assembly myDllAssembly =    System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll"); 


The myDllAssembly object can now be used to access the types contained inside MyDLL. To access a type contained inside MyDLL, System.Reflection.Assembly possesses a method called GetType(), which can return a System.Type that can be used to access all the members of the type we want to retrieve from inside MyDLL. Note that the System.Reflection.Assembly.GetType() method is not to be confused with the GetType() method possessed by all objects; they are related, but quite different, and we will discuss the other GetType() method later. Back to our example; let's say, there is a type inside MyDLL called MyDLLForm which inherits from System.Windows.Forms.Form and is contained in the namespace MyDLLNamespace. To obtain the System.Type of this, we could do the following:


System.Reflection.Assembly myDllAssembly =    System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
System.Type MyDLLFormType = myDllAssembly.GetType("MyDLLNamespace.MyDLLForm");



MyDLLFormType now holds the System.Type of MyDLLForm. We can now access all the members and contained types inside MyDLLForm from MyDLLFormType. However, using this GetType() method will not create an instance of MyDLLForm. To access a type contained inside MyDLL and create an instance of it, System.Reflection.Assembly possesses another method called CreateInstance(). Say, we wanted to create an instance of MyDLLForm, we could use something like this:


System.Reflection.Assembly myDllAssembly =   System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
Form MyDLLFormInstance = (Form)myDllAssembly.CreateInstance("MyDLLNamespace.MyDLLForm");





MyDLLFormInstance now holds an instance of MyDLLForm (remember that MyDLLForm inherits from Form). To create an instance of MyDLLForm, that method will invoke MyDLLForm's constructor. By way of that overload, CreateInstance is expecting a constructor that takes no arguments, as we only passed it the type name we want to create an instance of. However, let's say there is a constructor we want to use to create an instance of MyDLLForm that takes two arguments, a string and an int. To do that, and for example, to pass it a string of "Hi" and an integer value of 113 (one of my favorite numbers), we could use this:
System.Reflection.Assembly myDllAssembly =
   System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");

//the arguments we will pass
object[] argstopass = new object[] { (object)"Hi", (object)113 };

Form MyDLLFormInstance = (Form)myDllAssembly.CreateInstance("MyDLLNamespace.MyDLLForm",
     false, //do not ignore the case
     BindingFlags.CreateInstance, //specifies we want to call a ctor method
     null, //a null binder specifies the default binder will be used (works in most cases)
     argstopass, //the arguments (based on the arguments,
                 //CreateInstance() will decide which ctor to invoke)
     null, //CultureInfo is null so we will use
           //the culture info from the current thread
     null //no activation attributes
     );