Welcome to MSDN Blogs Sign in | Join | Help

Coherence With .Net

In one of my recent projects I was implementing Enterprise level caching using Coherence.

As you might be aware its written in Java and expects all the objects (that needs to be cached in it) in a Portable Object Format. This is to allow interoperability and platform independence. If the client is Java, the POF isn't mandatory, however if its .Net it is mandatory.

Things weren't too good to start with. I personally do not favor any platform for getting certain things done, but the fact of the matter is that Microsoft excels in product support. If you can find issues with any product, you are most likely to find remedies over the support site. With Coherence, and Oracle I am afraid things aren't the way they should. They need some effort here.

The issues I faced while implementing the solution are:
- Although my .Net class was derived from IPortableObject, I wasn't able to serialize int!!! There was no issue with strings. The error message was as generic as it can ever get - Java.Io.IoException: Unable to convert type -20 to a binary type. If you do a search you will not find anything helpful.
- If I tried to use one more class, it failed with the message: Unable to load type 1002. Please note that its suggested in the documents that custom user type IDs should be greater that 1000. So, my first type Employee was 1001, and the second type Contractor was 1002. It failed miserably, and like earlier found nothing over the Web.

So, I decided to try something else, knowing the fact that it needs objects in binary format, I used the following:

- Decorated the class in question with [Serializable] attribute
    [Serializable]
  public class Contractor : IPerson, IPortableObject

- Created the object and initialized it with values
   IPerson contractor = new Contractor();
  contractor.Name = "ABC";
  contractor.Address = "Karol Bagh";
  contractor.DoB = DateTime.Now;

- Initialized the cache
    cache = CacheFactory.GetCache("dist-session-cache");

- Created a binary formatter, a memory stream, serialized the object, and then inserted the array of bytes in binary format in the Coherence cache.
  BinaryFormatter binFormat = new BinaryFormatter();
  MemoryStream memStream = new MemoryStream();
  binFormat.Serialize(memStream, contractor);
  byte[] array = memStream.ToArray();
  cache.Insert(1, array);

- To deserilaize, I did the following:
  byte[] cachedObject = cache[1] as byte[];
  MemoryStream memStreamFromCache = new MemoryStream(cachedObject);
  IPerson p = (IPerson)binFormat.Deserialize(memStreamFromCache);


I am sure this is going to be helpful for all those using Coherence with .Net

See you soon with Splunk.

Posted by Sanjeet | 4 Comments
Filed under:

A walk in the park

I have written some Domain specific blogs. You can find them here:

http://sanjeetsahay.blogspot.com

I will resume my postings on Patterns and Frameworks soon. Till then :)

 

 

Posted by Sanjeet | 1 Comments
Filed under:

Creational - Factory Pattern

In continuation to my previous post, I am presenting you a sample code that implements Factory Pattern.

The overview:
 - We are using the Person, Gift and Letter classes as we did in the Abstract Factory Pattern implementation. This is just to show how you can use the same scenario against different patterns.
 - The abstract Person class is the Creator. Gift and Letter are Products.
 - The concrete creator classes are Employee and Colleague. The concrete Product classes are: Email, Postal for Letter; Flowers, Perfume for Gift.
 - The Creator has 2 abstract functions that create Products. the Concrete Classes override them to create different Products.
 - You can create an Array of Concrete objects for the Creator class.

Takeaways:
 - This pattern is particularly helpful in designing frameworks.
 - The Creator relies on its subclasses to define the factory method to return the appropriate ConcreteProduct.
 - There is no Client class.

The Creator Class:

   1: public abstract class Person
   2:     {
   3:         public abstract Gift CreateGift();
   4:         public abstract Letter CreateLetter();
   5:     }

The Concrete Classes:

   1: public class Employee: Person
   2:     {
   3:         public override Gift CreateGift()
   4:         {
   5:             return new Flowers();
   6:         }
   7:         public override Letter CreateLetter()
   8:         {
   9:             return new Email();
  10:         }
  11:     }
  12:     
  13:     public class Colleague: Person
  14:     {
  15:         public override Gift CreateGift()
  16:         {
  17:             //throw new NotImplementedException();
  18:             return new Perfume();
  19:         }
  20:  
  21:         public override Letter CreateLetter()
  22:         {
  23:             //throw new NotImplementedException();
  24:             return new Postal();
  25:         }
  26:     }

The Products - Letter and Gift; Concrete Products Email, Postal, Flowers, and Perfume

   1: public abstract class Letter
   2:     {
   3:     }
   4:     
   5:     public class Email: Letter
   6:     {
   7:         public Email()
   8:         {
   9:             Console.WriteLine("Email Created");
  10:         }
  11:     }
  12:     
  13:     public class Postal: Letter
  14:     {
  15:         public Postal()
  16:         {
  17:             Console.WriteLine("Postal Created");
  18:         }
  19:     }
  20:     
  21:     public abstract class Gift
  22:     {        
  23:     }
  24:     
  25:     public class Flowers: Gift
  26:     {
  27:         public Flowers()
  28:         {
  29:             Console.WriteLine("Flowers Created");
  30:         }
  31:     }
  32:     
  33:     public class Perfume: Gift
  34:     {
  35:         public Perfume()
  36:         {
  37:             Console.WriteLine("Perfume Created");
  38:         }
  39:     }

The usage from within application:

   1: static void Main(string[] args)
   2:         {
   3:             Person[] people = new Person[2];
   4:             people[0] = new Employee();
   5:             people[1] = new Colleague();
   6:             
   7:             foreach(Person person in people)
   8:             {
   9:                 Console.WriteLine(person.CreateGift());
  10:                 person.CreateLetter();
  11:             }
  12:             Console.Read();
  13:         }

Hope it helps. Do write to me in case of any question/suggestions.

Posted by Sanjeet | 1 Comments
Filed under:

Software Design Patterns - Creational Patterns

This happens to be the first of my articles on Software Design Patterns. I will present some basics followed by implementation of the pattern.

These patterns help make a system independent of how its objects are created, composed and represented.
A class creational pattern uses inheritance to vary the class that’s instantiated, whereas the object creational pattern will delegate instantiation to another object.

In creational patterns emphasis shifts away from hard coding a fixed set of behaviors towards defining a smaller set of fundamental behaviors that can be composed into any number of more complex ones. Thus object composition becomes more important than class inheritance.
Some widely used patterns in this category are:

Abstract Factory
 - The main purpose is to create objects for the product class.

 - The break-up of classes involved is as follows:
  > You need an abstract factory class which acts as a base to some concrete classes.
  > You need an abstract product/entity class which will act as a base class for some fixed number of concrete product classes.
  > A client, which always uses the interfaces declared by the abstract factory and product classes.
  > The factory class is not abstract; it in fact uses the Singleton pattern to create only 1 instance. It is used by the product classes to create new instances.

 - You can use this pattern in the following cases:
  > A system is independent in terms of how its products are created, composed and represented.
  > You want to provide a class library of things, and you don’t want to reveal the implementations but interfaces.
  > The number of products is defined.

 - Advantages:
  > Concrete classes are isolated. Product class names are isolated in the implementation of the concrete factory.
  > Product families can be changed easily.
  > Promotes consistency among products.

 - Disadvantages:
  > Supporting new kinds of products is difficult. It requires you to change the abstract and concrete factory classes at number of places.

Factory
 - This pattern defines an interface for creating an object, but let subclasses decide which class to instantiate.

 - The break-up of the classes involved is as follows:
  > You need a Product and a Creator
  > Concrete classes for Product and Creator.
  > Creator relies on its subclasses to define factory method so that it returns an instance of the appropriate Concrete Product.

 - The following happens:
  > You may create multiple Creator classes, and multiple Product classes.
  > Each Creator has something like a Create() function that creates one/more Products.
  > From a client, you create an array of Creator base abstract class. This array can have objects from any of the inherited Creator classes.
  > The inherited Creator classes then create one/more Products for the client.

Builder
 - This pattern is useful when you want to separate the construction of a complex object from its representation. This enables the same construction process to create different representations.
 - It involves a Builder and a Director.
 - Use this pattern if:
  > You need to keep the algorithm of creating a complex object separate from the parts that make it up.
  > The construction process must allow different representations for the object that’s constructed.

 - The break-up of the classes involved are as follows:
  > There is an abstract builder class for creating parts of a product object.
  > You need a Concrete Builder class to construct and assemble parts of the product by implementing Builder.
  > A Director class that constructs an object by using the Builder.
  > The Product classes that represent the complex object under construction. They do not require an Abstract base class as their implementations have to be very different.

 - The following happens:
  > A client creates the Director object and configures it with the desired Builder object.
  > Director notifies the Builder to build a Product. Builder then adds parts to the Product.
  > The client retrieves the Product from the builder.

 - Advantages:
  > Director has no direct interaction with the Product so you can easily change/modify them.
  > It isolates the code for construction and representation.
  > This pattern constructs products step by step under Director’s control.



Posted by Sanjeet | 1 Comments
Filed under:

Creational - Abstract factory Pattern

In continuation to my previous post, I am presenting you a sample code that implements Abstract Factory Pattern.

The overview:
 - This implementation contains a factory called Person.
 - The Product/Entity class is represented by 2 abstract classes called Gift and Letter.
 - The client class is called Client.
 - Employee and Colleague inherits from Person.
 - Email inherits Letter and Flowers inherit Gift.
 - Client creates/receives an instance of Person class which creates objects for Gift and Letter.

Takeaways:
 - As discussed earlier, Creational Patterns focus on creating objects of Product.
 - The complexity of this pattern increases as the number of Product increases. You have to add more virtual functions at the Person(Factory) level. Then override those functions at the Concrete classes of the Factory(eg., Employee, Colleague)

The Person class(Factory), this implementation uses the Singleton pattern with Lazy Initialization to make sure that there is only 1 instance in the application.

   1: public class Person
   2:     {
   3:         /// <summary>
   4:         /// Static variable of the class to see if its already instantiated
   5:         /// </summary>
   6:         private static Person _p;      
   7:  
   8:         /// <summary>
   9:         /// The virual functions to create a Gift Product
  10:         /// </summary>
  11:         /// <returns></returns>
  12:         public virtual Gift CreateGift()
  13:         {
  14:             return new Flowers();
  15:         }
  16:         
  17:         /// <summary>
  18:         /// The virual functions to create a Letter Product
  19:         /// </summary>
  20:         /// <returns></returns>
  21:         public virtual Letter CreateLetter()
  22:         {
  23:             return new Email();
  24:         }
  25:         
  26:         /// <summary>
  27:         /// This static method gets you the single instance of this class
  28:         /// </summary>
  29:         /// <returns></returns>
  30:         public static Person GetInstance()
  31:         {
  32:             if (_p == null)
  33:             {
  34:                 _p = new Person();
  35:             }
  36:             return _p;
  37:         }
  38:         
  39:         /// <summary>
  40:         /// Constructor with restricted access
  41:         /// </summary>
  42:         protected Person(){
  43:         }        
  44:     }

The Employee Concrete Class:

   1: /// <summary>
   2:     /// This is one of the Concrete classes which isolated from the client
   3:     /// </summary>
   4:     public class Employee: Person
   5:     {
   6:         /// <summary>
   7:         /// Constructor to the class
   8:         /// </summary>
   9:         public Employee():base()
  10:         {
  11:             
  12:         }
  13:  
  14:         /// <summary>
  15:         /// Override the virtual declared in the base class.
  16:         /// This function creates and returns one of the products - Flowers
  17:         /// </summary>
  18:         /// <returns></returns>
  19:         public override Gift CreateGift()
  20:         {
  21:             return new Flowers();
  22:         }
  23:  
  24:         /// <summary>
  25:         /// Override the virtual declared in the base class.
  26:         /// This function creates and returns one of the products - Email
  27:         /// </summary>
  28:         /// <returns></returns>
  29:         public override Letter CreateLetter()
  30:         {
  31:             return new Email();
  32:         }
  33:     }

The Colleague Concrete Class:

   1: /// <summary>
   2:     /// This is one of the Concrete classes which isolated from the client
   3:     /// </summary>
   4:     public class Colleague: Person
   5:     {
   6:         /// <summary>
   7:         /// Constructor to the class
   8:         /// </summary>
   9:         public Colleague():base()
  10:         {
  11:         }
  12:  
  13:         /// <summary>
  14:         /// Override the virtual declared in the base class.
  15:         /// This function creates and returns one of the products - Flowers
  16:         /// </summary>
  17:         /// <returns></returns>
  18:         public override Gift CreateGift()
  19:         {
  20:             return new Flowers();
  21:         }
  22:  
  23:         /// <summary>
  24:         /// Override the virtual declared in the base class.
  25:         /// This function creates and returns one of the products - Email
  26:         /// </summary>
  27:         /// <returns></returns>
  28:         public override Letter CreateLetter()
  29:         {
  30:             return new Email();
  31:         }
  32:     }

The Gift and Letter Abstract Product Classes:

   1: /// <summary>
   2:     /// This is the Product type #1
   3:     /// </summary>
   4:     public abstract class Gift
   5:     { 
   6:         protected string _name;
   7:         
   8:         public virtual string Name
   9:         {
  10:             get;set;
  11:         }
  12:              
  13:         public Gift()
  14:         {
  15:             _name = "Gift Constructor";        
  16:         }        
  17:     } 
  18:  
  19: /// <summary>
  20:     /// This is the Product type #2
  21:     /// </summary>
  22:     public abstract class Letter
  23:     {
  24:         protected string _purpose;
  25:                 
  26:         public Letter()
  27:         {
  28:             _purpose = "Letter Constructor";
  29:         }
  30:  
  31:         public virtual string Purpose
  32:         {
  33:             get;
  34:             set;
  35:         }
  36:     }

The Products - Email and Flowers:

   1: /// <summary>
   2:     /// This is product #1 of product type #1
   3:     /// </summary>
   4:     public class Flowers: Gift
   5:     {
   6:         public Flowers()
   7:         {
   8:             _name = "Flowers Constructor";
   9:         }
  10:         
  11:         public override string Name
  12:         {
  13:             get
  14:             {
  15:                 return _name;
  16:             }
  17:             set
  18:             {
  19:                 _name = value;
  20:             }
  21:         }      
  22:     }
  23:  
  24: /// <summary>
  25:     /// This is product #1 of product type #2
  26:     /// </summary>
  27:     public class Email: Letter
  28:     {
  29:     
  30:         public Email()
  31:         {
  32:             _purpose = "Email Constructor";
  33:         }
  34:         public override string Purpose
  35:         {
  36:             get
  37:             {
  38:                 return _purpose;
  39:             }
  40:             set
  41:             {
  42:                 _purpose = value;
  43:             }
  44:         }
  45:     }

 

Please write to me if you have any questions/suggestions.

Posted by Sanjeet | 1 Comments
Filed under:

How To: Use SqlMetal.exe to Create a Class from XML and Database

If you don't have Visual C# Codename Orcas Express Edition installed on your development machine, and you are using Visual Studio 2005 with the LINQ 2006 CTP, then SqlMetal.exe is something that you must lookout for.

It is the O/R mapper that you must use to create a strongly typed class, and use it with DLinq.

You can find SqlMetal.exe at: %systemdrive%\Program Files\LINQ Preview\Bin folder.

Its used as following:

usage: sqlmetal [options] [<input file>]
options:
  /server:<name>     database server name
  /database:<name>   database catalog on server
  /user:<name>       login user id
  /password:<name>   login password
  /views             extract database views
  /functions         extract database functions
  /sprocs            extract stored procedures
  /xml[:file]        output as xml
  /code[:file]       output as source code
  /map[:file]        generate xml mapping file instead of attributes
  /language:xxx      language for source code (vb,csharp)
  /namespace:<name>  namespace used for source code
  /pluralize         auto-pluralize table names
  /dataAttributes    auto-generate DataObjectField and Precision attributes
  /timeout:<seconds> timeout value in seconds to use for database commands

examples:
To generate an XML file with extracted SQL metadata
  sqlmetal /server:myserver /database:northwind /xml:mymeta.xml

To generate an XML file with extracted SQL metadata from an .mdf file
  sqlmetal /xml:mymeta.xml mydbfile.mdf

To generate source code from an XML metadata file
  sqlmetal /namespace:nwind /code:nwind.cs /language:csharp mymetal.xml

To generate source code from SQL metadata directly
  sqlmetal /server:myserver /database:northwind /namespace:nwind /code:nwind.cs /language:csharp

To create an XML file from a database like Northwind, I copied the .mdf as suggested by the above help and pasted it to the same folder. I used the following command:
sqlmetal /xml:northwind.xml Northwind.mdf
but it failed with:

Unhandled Exception: System.Data.SqlClient.SqlException: An error has occurred while establishing a
connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fac
t that under the default settings SQL Server does not allow remote connections. (provider: SQL Netwo
rk Interfaces, error: 26 - Error Locating Server/Instance Specified)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConne
ction)
I thought its asking for the server name, so I tried this:
sqlmetal /xml:northwind.xml /server:myserver Northwind.mdf
it also failed with the following error:
Unhandled Exception: System.Data.SqlClient.SqlException: An attempt to attach an auto-named database
 for file Northwind.mdf failed. A database with the same name exists, or specified file cannot be op
ened, or it is located on UNC share.
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConne
ction)

The command that worked is following:
sqlmetal /server:myserver /database:Northwind /xml:northwind.xml

Then I thought of creating a class out of the generated XML. I used the following command and it worked the first time:
sqlmetal /code:Northwind.cs /language:csharp Northwind.xml

Creating a class file directly from the database is pretty starightforward, I used the following command:
sqlmetal /server:myserver /database:Northwind /code:Northwind.cs /language:csharp

 

C# IDE Support for Visual Studio 2005/C# 2005 Express

While this preliminary IDE support greatly enhances the editing experience when writing C# 3.0 code in VS 2005, the language service and compiler are still very much in an alpha phase. In the event of a compiler error, many more errors may be reported than are actually present. If you see a large number of errors when building C# 3.0 code, fix the top error in the error list first and build after each fix.

Follow these steps to enable LINQ IDE support for Visual Studio 2005 and Visual C# 2005 Express:

First, verify that you are running the release version of Visual Studio 2005 or Visual C# 2005 Express. The language service that will be installed only works with the English version of VS 2005/C# 2005 Express and may cause severe problems if installed on earlier versions. You can verify your version by selecting Help\About in Visual Studio 2005.
Shut down any running instances of Visual Studio.
Open the \bin folder under the LINQ preview installation directory and run “Install C# IDE Support”.
Start VS 2005/C# 2005 Express.

Follow these steps to restore your original VS 2005/C# 2005 Express language service:

Shut down any running instances of Visual Studio.
Open the \bin folder under the LINQ preview installation directory and run “Uninstall C# IDE Support”.
Start VS 2005/C# 2005 Express.

Posted by Sanjeet | 4 Comments
Filed under: ,

How To: Seemlessly Export Data From Database to XML using LINQ

 

While exploring a number of neat features available in the Visual C# Orcas Express Edition, you will see the following:

There is no namespace like DLinq, or XLinq anymore, they are replace with more meaningful
System.Data.Linq and
System.Xml.Linq

However, the latter appears by default in a console application, System.Data.Linq will be added to the references once the O/R mapper a.k.a .dbml file is added. In the express Edition, you can connect to a .mdf, .mdb, or a .sdf(Sql Server Compact Edition) databases.

After instantiating the DataContext class, you will be able to explore its rich features supported with Intellisence.

Apart from that the XML.Linq namespace has got some neat and intuitive features. My favorite is:
System.Xml.Linq.XElement xlinq = new XElement(XName name, object content);

As you would expect from it, any object returning values compatible to IEnumerable is taken care of by the constructor... all by itself.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            NorthwindDataContext north = new NorthwindDataContext();
            //sample query, not related to this demo!!
            var products = from p in north.Products
                           where p.ProductID > 10 && p.ProductID < 200
                           select new{
                                      p.ProductName,
                                      p.UnitPrice
                                  };
            //the actual thing!!!
            System.Xml.Linq.XElement xlinq = new XElement("Products",
                                             from p in north.Products
                                             where p.ProductName.StartsWith("S")
                                             select new XElement("Product", new XAttribute("UnitPrice", p.UnitPrice),
                                                    new XAttribute("QuantityPerUnit", p.QuantityPerUnit), 
                                                        new XElement("ProductName", p.ProductName),
                                                    new XElement("SupplierName", p.Supplier.CompanyName)
                                                        )
                                             );
            xlinq.Save("NewXML.xml");
            Console.Write(xlinq);            
            Console.Read();
        }
    }    
}

The output in the (command window) looks like the following:

Check out this space, lots more coming up...

Microsoft ROCKS!!!

Posted by Sanjeet | 1 Comments
Filed under: ,

LINQ Lists - Anonymous Methods and Lambda Expressions

 

Year: 2005 A.D.
The C# 2.0 specification is released in the month of September. It talks about "new" features. We were introduced with a new "in-line" feature of using delegates. We called it "Anonymous Methods". Needless to say, its named as such because:
- Its Anonymous (no method name is given)
- Its InLine (How can you call something without a name, makes sense doesn't it?)

Year: 2006 A.D.
The C# 3.0 specification is released in the month of May. It talks about new features. Among a number of path breaking innovative ideas, we have something called "Lambda Expressions". It claims to provide more concise, functional syntax for writing anonymous methods.

Lets checkout the basic syntax of Anonymous Methods:

delegate void D(int x); 
D d1 = delegate { }; // Ok 
D d2 = delegate() { }; // Error, signature mismatch 
D d3 = delegate(long x) { }; // Error, signature mismatch 
D d4 = delegate(int x) { }; // Ok 
D d5 = delegate(int x) { return; }; // Ok 
D d6 = delegate(int x) { return x; }; // Error, return type mismatch 
delegate void E(out int x); 
E e1 = delegate { }; // Error, E has an out parameter 
E e2 = delegate(out int x) { x = 1; }; // Ok 
E e3 = delegate(ref int x) { x = 1; }; // Error, signature mismatch 
delegate int P(params int[] a);
P p1 = delegate { }; // Error, end of block reachable 
P p2 = delegate { return; }; // Error, return type mismatch 
P p3 = delegate { return 1; }; // Ok 
P p4 = delegate { return "Hello"; }; // Error, return type mismatch 
P p5 = delegate(int[] a) { // Ok 
return a[0]; }; 
P p6 = delegate(params int[] a) { // Error, params modifier 
return a[0]; }; 
P p7 = delegate(int[] a) { // Error, return type mismatch 
if (a.Length > 0) 
return a[0]; 
return "Hello"; 
}; 
delegate object Q(params int[] a); 
Q q1 = delegate(int[] a) { // Ok 
if (a.Length > 0) 
return a[0]; 
return "Hello"; 
};

The best example of an anonymous method is when a delegate is used as an Event Handler:

Without Anonymous:

MyButton.Click += new EventHandler(MyButtonClicked);
void MyButtonClicked(object sender, EventArgs e)
{
MessageBox.Show("Hello World!");
}

With Anonymous:

MyButton.Click += delegate{
MessageBox.Show("Hello World!");
}

From the above comparison, you can make out that using InLine Functions, we do not need to:
- pass arguments across functions.
- you can use the scope level variables easily.
But, it has tradeoffs which involve code readability and reusability hassles. As the age old saying goes about InLine Functions: Use it efficiently, as its faster than calling functions but slightly difficult to manage.

Lambda Expressions

It is written as a parameter list, followed by the => (slanted lambda?) token, followed by an expression or a statement block.

class Program
{
    static void Main(string[] args)
    {
        List<Vehicle> vlist = new List<Vehicle>
                              {
                                  new Vehicle{Make="Mercedes", Model="Benz", Mileage=12},
                                  new Vehicle{Make="Renault", Model="Logan", Mileage=15},
                                  new Vehicle{Make="Honda", Model="Accord", Mileage=12},
                              };
        IEnumerable<Vehicle> vehicles = vlist.Where(v => v.Mileage > 10);
        foreach (Vehicle v in vehicles)
        {
            Console.WriteLine(v.Make);
            Console.WriteLine(v.Model);
            Console.WriteLine(v.Mileage);
            Console.WriteLine("-----------------");
        }
        Console.Read();
    }
}
 
public class Vehicle
{
    public string Make;
    public string Model;
    public int Mileage;
}

In the above example:
IEnumerable<Vehicle> vehicles = vlist.Where(v => v.Mileage > 10);

The Lambda Expression:
v => v.Mileage > 10

replaces:
new delegate(Vehicle v){
v.Mileage > 10;
}

It can also be replaced by:

IEnumerable<Vehicle> vehicles = from v in vlist
                                            where v.Mileage > 12
                                            select v;

Try this: The Evolution Of LINQ And Its Impact On The Design Of C#

These samples were created using: Microsoft Visual C# Codename "Orcas" Express Edition

Posted by Sanjeet | 1 Comments
Filed under: ,

The Var Of The Worlds

Hello folks,

This time we will explore LINQ over a series of Posts.

As you must be knowing the age old "var" is back. But, is it the same old var that used to be in VB 6.0 days?

Precisely its not the same it has got a number of new features:
- You have to declare and instantiate it at the same line of code. Reason: It is smart enough to understand the assigned data type, and it becomes it.
 
var s = int.MaxValue; // it becomes Int32
var s2 = double.MaxValue; // it becomes double
var s3 = "The Var Of The Worlds" // string

- You cannot assign multiple data types to it. Any attempt to do so results in a compile time error.

Code with var:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         var s = from m in typeof(string).GetMethods()
   6:                 select m.Name;
   7:         foreach(string str in s)
   8:         {
   9:             Console.WriteLine(str);
  10:         }
  11:         Console.Read();
  12:     }
  13: }

Code without a var:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         IEnumerable<string> s  = 
   6:             from m in typeof(string).GetMethods()
   7:             select m.Name;
   8:  
   9:         foreach(string str in s)
  10:         {
  11:             Console.WriteLine(str);
  12:         }
  13:         Console.Read();
  14:     }
  15: }
Posted by Sanjeet | 1 Comments
Filed under: ,

How To: Create an efficient data driven page with Business Objects, GridView, Custom paging, and AJAX

Preface:

I have seen a large number of cases where the customer complaint of performance and scalability issues
when they create/manage a data-aware application. That’s when I decided that I should come up with
something that is concise, efficient, and easy to implement for developers.
Here, is what I created a couple of days ago.

GridView is awesome, and if you combine it with Sql Server 2005, DetailsView and FormView
you have a formidable force to build a rich data aware page. You can achieve almost everything
that you may require on a page without even writing a single line of code in your ASPX,
even Custom paging (it requires you to write some views in TSQL).

Requirement Analysis:

  1. A simple page for that has to fetch a large amount of data (more than 10K rows) from a remote database.
  2. I need paging and sorting support with CRUD on the page
  3. I need a way to customize the GridView control
  4. I need to use a 3-tier structure where I have Data Access Layer, Business Access Layer, and the Presentation Layer.
  5. Everybody is talking and using AJAX, so I need that also. I like the word "Partial-Rendering" ;)

Prerequisites:

You need Visual Studio 2005, Sql Server 2005, and ASP.net AJAX 1.0

Architecture:

The DAL:

It is implemented using a Dataset. This is a strongly typed dataset, and contains all the required Stored procedures and queries.

We will concentrate on the class "Entity" only.

The following is the implementation of the BAL.

The presentation layer has only 1 page for now. I hope this is what we need now. It looks like the following:

As we can see, we have highly Customized the datagrid. Lets dive deeper into the functionality.

The BAL:

The following code snippet contains Insert, Edit, and Delete functions required to do usual stuff. Its self explanatory.

/// <summary>
/// This is the Insert function for the class. 
/// It takes all the columns as arguments and uses a DatabaseDirect mode to update the database directly.
/// </summary>
/// <param name="EntityID"></param>
/// <param name="UserID"></param>
/// <param name="Title"></param>
/// <param name="Description"></param>
/// <returns></returns>
public int Insert(int EntityID, string UserID, string Title, string Description)
{
    int rowsAffected = 0;
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //Update the DB directly
        //Insert function is defined in the DataSet
        rowsAffected = ad.Insert(UserID, Title, Description);
    }
    catch
    {
        //throw all the error that are catched here
        throw;
    }
    return rowsAffected;
}
 
/// <summary>
/// This is the Edit function for the class. 
/// It takes all the columns as arguments and uses a DatabaseDirect mode to update the database directly.
/// </summary>
/// <param name="EntityID"></param>
/// <param name="UserID"></param>
/// <param name="Title"></param>
/// <param name="Description"></param>
/// <returns></returns>
public int Edit(int EntityID, string UserID, string Title, string Description)
{
    int rowsAffected = 0;
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //Update function is defined in the DataSet
        rowsAffected = ad.Update(UserID, Title, Description, EntityID, EntityID);
    }
    catch
    {
        //throw all the error that are catched here
        throw;
    }
    return rowsAffected;
}
 
/// <summary>
/// This is the Delete function for the class. 
/// It takes all the columns as arguments and uses a DatabaseDirect mode to update the database directly.
/// </summary>
/// <param name="EntityID"></param>
/// <returns></returns>
public int Delete(int EntityID)
{
    int rowsAffected = 0;
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //Delete function is defined in the DataSet
        rowsAffected = ad.Delete(EntityID);
    }
    catch
    {
        //throw all the error that are catched here or apply
        throw;
    }
    return rowsAffected;
}

Now the Select functions. These functions are the key to our demo. We will explain each of them at a later part in this post.

/// <summary>
/// This function selects all the records filtered by UserID
/// </summary>
/// <param name="UserID"></param>
/// <returns></returns>
public ManageabilityDS.EntityDataTable Select(string UserID)
{
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetEntitiesByUser function is defined in the DataSet
        return ad.GetEntitiesByUser(UserID);
    }
    catch
    {
        throw;
    }
}
 
/// <summary>
/// This function selects all the records filtered by UserID and EntityID
/// </summary>
/// <param name="UserID"></param>
/// <param name="EntityID"></param>
/// <returns></returns>
public ManageabilityDS.EntityDataTable Select(string UserID, int EntityID)
{
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetEntityByUserAndEntityID function is defined in the DataSet
        return ad.GetEntityByUserAndEntityID(UserID, EntityID);
    }
    catch
    {
        throw;
    }
}   
 
/// <summary>
/// This function gets the maximum rows from the table after its sequenced using Row_number
/// </summary>
/// <param name="UserID"></param>
/// <returns></returns>
public long GetMaxNumberOfRows(string UserID)
{
    long num = 0;
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetNumberOfRows function is defined in the DataSet
        num = (long)ad.GetNumberOfRows(UserID);
        return num;
    }
    catch
    {
        throw;
    }
}
 
/// <summary>
/// This function return a strongly type list containing paged data
/// A benefit of using Generic here is to minimize the size of the object
/// </summary>
/// <param name="UserID"></param>
/// <param name="StartRowIndex"></param>
/// <param name="MaximumRows"></param>
/// <returns></returns>
public List<Entity> Select(string UserID, int StartRowIndex, int MaximumRows)
{
    ManageabilityDS.EntityDataTable tbl = null;
    List<Entity> t = new List<Entity>(); 
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetPagedEntityByUser function is defined in the DataSet
        tbl = ad.GetPagedEntityByUser(StartRowIndex, MaximumRows, UserID);
        //fill the strongly typed List with data
        foreach (ManageabilityDS.EntityRow row in tbl.Rows)
        {
            Entity en = new Entity();
            en.EntityID = row.EntityID;
            en.UserId = row.UserID;
            en.Title = row.Title;
            en.Description = row.Description;
            t.Add(en);
        }
        return t;
    }
    catch
    {
        throw;
    }
}
 
/// <summary>
/// This function return a strongly type list containing paged and sorted data
/// </summary>
/// <param name="UserID"></param>
/// <param name="StartRowIndex"></param>
/// <param name="MaximumRows"></param>
/// <param name="ColumnToOrder"></param>
/// <param name="OrderDirection"></param>
/// <returns></returns>
public List<Entity> Select(string UserID, int StartRowIndex, int MaximumRows, string ColumnToOrder, string OrderDirection)
{
    ManageabilityDS.EntityDataTable tbl = null;
    List<Entity> t = new List<Entity>();
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetPagedEntityByUserOrdered function is defined in the DataSet
        tbl = ad.GetPagedEntityByUserOrdered(StartRowIndex, MaximumRows, UserID, ColumnToOrder, OrderDirection);
        //fill the strongly typed List with data
        foreach (ManageabilityDS.EntityRow row in tbl.Rows)
        {
            Entity en = new Entity();
            en.EntityID = row.EntityID;
            en.UserId = row.UserID;
            en.Title = row.Title;
            en.Description = row.Description;
            t.Add(en);
        }
        return t;
    }
    catch
    {
        throw;
    }
}

 

The Presentation Layer:

The datagrid looks like following in code:

<asp:GridView ID="MainGrid" runat="server" EnableViewState="true" AutoGenerateColumns="False"
    CellPadding="4" ForeColor="#333333" Width="100%" PageSize="2" DataKeyNames="EntityID"
    EmptyDataText="No data available" OnRowDeleting="MainGrid_RowDeleting">
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <RowStyle BackColor="#EFF3FB" />
    <EditRowStyle BackColor="#2461BF" />
    <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle Font-Bold="True" HorizontalAlign="Left" />
    <AlternatingRowStyle BackColor="White" />
    <Columns>
        <asp:TemplateField HeaderText="Details">
            <HeaderStyle Font-Bold="True" Width="80%" />
            <ItemTemplate>
                <table width="100%">
                    <tr>
                        <td width="15%">
                            <span><b>ID:</b></span>
                        </td>
                        <td>
                            <asp:Label ID="EntityIDLabel" runat="server" Text='<%#Bind("EntityID")%>'></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="silver" colspan="2">
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <span><b>Title:</b></span>
                        </td>
                        <td>
                            <asp:Label ID="TitleLabel" runat="server" Text='<%#Bind("Title")%>'></asp:Label>
                        </td>
                    </tr>
                    <tr>
                        <td bgcolor="silver" colspan="2">
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <span><b>Description:</b></span>
                        </td>
                        <td>
                            <asp:Label ID="DescriptionLabel" runat="server" Font-Italic="true" Text='<%#Bind("Description")%>'></asp:Label>
                        </td>
                    </tr>
                </table>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Options">
            <ItemTemplate>
                <table width="100%">
                    <tr>
                        <td valign="top">
                            <asp:LinkButton ID="Select" CommandName="Select" runat="server" Text="Select"></asp:LinkButton>
                        </td>
                    </tr>
                    <tr>
                        <td valign="top">
                            <asp:LinkButton ID="Delete" CommandName="Delete" runat="server" Text="Delete" OnClientClick="return confirm('Are you sure you want to delete this record?');"></asp:LinkButton>
                        </td>
                    </tr>
                </table>
            </ItemTemplate>
            <HeaderStyle Font-Bold="False" />
        </asp:TemplateField>
    </Columns>
</asp:GridView>

We have made extensive use of template columns to give it a different look.
To bind the data we simply used: Text='<%#Bind("Column_Name")%>' e.g.
Text = '<%#Bind("Title")%>'

Notice that the paging is disabled. DataKeyNames is set to the Primary Key,
and we have defined OnRowDeleting event for deleting a record.

Remember those days, when we used to code OnItemDatBound event in
ASP.Net 1.1 to bind the Delete button attribute with an OnClick event. Now,
its as easy as assigning OnClientClick = [required javascript] e.g.
OnClientClick = "return confirm(Are you sure?)"
 

The DetailsView looks like the following in code:

<asp:DetailsView ID="EntityDetailsView" runat="server" AutoGenerateRows="False" DataKeyNames="EntityID"
    DataSourceID="odsDetailView" Height="50px" Width="100%" OnItemInserted="EntityDetailsView_ItemInserted"
    OnItemUpdated="EntityDetailsView_ItemUpdated">
    <Fields>
        <asp:BoundField DataField="EntityID" HeaderText="ID:" InsertVisible="False" ReadOnly="True"
            SortExpression="EntityID" HeaderStyle-Width="15%" HeaderStyle-Font-Bold="true" />
        <asp:BoundField DataField="UserID" HeaderText="UserID" SortExpression="UserID" Visible="False" />
        <asp:TemplateField HeaderText="Title:" HeaderStyle-VerticalAlign="Top" SortExpression="Title"
            HeaderStyle-Font-Bold="true">
            <EditItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Title") %>' CssClass="textbox"></asp:TextBox>
            </EditItemTemplate>
            <InsertItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Title") %>' CssClass="textbox"></asp:TextBox>
            </InsertItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" Text='<%# Bind("Title") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Description:" HeaderStyle-VerticalAlign="Top" SortExpression="Description"
            HeaderStyle-Font-Bold="true">
            <EditItemTemplate>
                <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("Description") %>' CssClass="textarea"
                    TextMode="MultiLine" Rows="5" Width="80%"></asp:TextBox>
            </EditItemTemplate>
            <InsertItemTemplate>
                <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("Description") %>' CssClass="textarea"
                    TextMode="MultiLine" Rows="5" Width="80%"></asp:TextBox>
            </InsertItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" Text='<%# Bind("Description") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:CommandField ShowEditButton="True" ShowInsertButton="True" />
    </Fields>
</asp:DetailsView>

Check out the following:

We have set DataKeyField to the Primary Key and set the datasource ID to
an ObjectDataSource called "odsDetailView". It fetches all the data via the
Business layer and it doesn't need to go to the DAL.

The ObjectDataSource truely helps us to build a 3-tier application.
Earlier, in this model the UI layer used to bind directly to the Data layer.
This actually used to break the tier, and caused scalability and
maintenance hassles.

We have OnItemInserted and OnItemUpdated events handled to refresh the
GridView whenever an update is made using the DetailsView.

<asp:DetailsView ID="EntityDetailsView" runat="server" AutoGenerateRows="False" DataKeyNames="EntityID"    
 DataSourceID="odsDetailView" Height="50px" Width="100%" OnItemInserted="EntityDetailsView_ItemInserted"    
 OnItemUpdated="EntityDetailsView_ItemUpdated">

So, whenever you click on the Select button in a row inside the GridView,
the ObjectDataSource retrieves the PrimaryKey from the SelectedValue property
of the GridView. See the definition of the ASP ControlParameter below.

<SelectParameters>
    <asp:SessionParameter DefaultValue="fareast\sanjeets" Name="UserID" SessionField="UserID"
        Type="String" />
    <asp:ControlParameter ControlID="MainGrid" Name="EntityID" PropertyName="SelectedValue"
        Type="Int32" />
</SelectParameters>

 

So far, we have discussed how the controls interact with each other to give you
you a nice clutter free UI for simple operations like Insert, Update, and Delete.
Now, lets move on the bigger picture.

I have entered about 50K rows in the Entities table.

Fair enough, I need paging now. Talking about normal paging would be painful,
so thats ruled out (I hope you understand what does the normal paging will
do, it will bring all 50K rows and show you 10 rows... it hurts).

GridView alongwith ObjectDataSource brings to CustomPaging, so all you have to do,
is to use the magic of Row_Number in Sql Server 2005 to bring sequential rows.
But, thats again almost codeless. So, you have lesser control over it? I hope you
still remember scalability? right?

Refer to Paging through lots of data efficiently (and in an Ajax way) with ASP.NET 2.0 for more
information about how to almost codelessly implement custom paging.

 

Lets take a look into the 2 Stored Procedures:
The first one as the name suggests Selects Paged rows by a given condition.

ALTER Procedure [dbo].[SelectPagedEntityByUser]
    @StartRowIndex int,
    @MaximumRows int,
    @UserID varchar(50)
AS
Select EntityID, UserID, Title, [Description]
    From AllEntities
Where 
    SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
    AND UserID = @UserID

It uses the following view:

ALTER View [dbo].[AllEntities]
AS
Select 
    EntityID, UserID, Title, [Description], 
    Row_Number() Over(Order By EntityID) as SrNum
From Entity

The second one, as the name suggests Selects Paged rows by a given condition with a sort
condition:

ALTER Procedure [dbo].[SelectPagedEntityByUserOrdered]
    @StartRowIndex int,
    @MaximumRows int,
    @UserID varchar(50),
    @ColumnToOrder varchar(50),
    @OrderDirection varchar(10)
AS
if @ColumnToOrder like '%ID'
begin
    if @OrderDirection = 'asc'
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By EntityID) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
    else
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By EntityID DESC) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
end
if @ColumnToOrder = 'title'
begin
    if @OrderDirection = 'asc'
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By Title) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
    else
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By Title DESC) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
end
if @ColumnToOrder like 'desc%'
begin
    if @OrderDirection = 'asc'
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By [Description]) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
    else        
        begin
            Select EntityID, UserID, Title, [Description]
                From (
                        Select 
                            EntityID, UserID, Title, [Description], 
                            Row_Number() Over(Order By [Description] DESC) as SrNum
                        From Entity
                    ) as temp
            Where 
                SrNum Between @StartRowIndex AND (@StartRowIndex+@MaximumRows)-1
                AND UserID = @UserID
        end
end

Their corresponding functions in the BL looks like the following:
Notice the use of Generics.
For the unsorted:

/// <summary>
/// This function return a strongly type list containing paged data
/// A benefit of using Generic here is to minimize the size of the object
/// </summary>
/// <param name="UserID"></param>
/// <param name="StartRowIndex"></param>
/// <param name="MaximumRows"></param>
/// <returns></returns>
public List<Entity> Select(string UserID, int StartRowIndex, int MaximumRows)
{
    ManageabilityDS.EntityDataTable tbl = null;
    List<Entity> t = new List<Entity>(); 
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetPagedEntityByUser function is defined in the DataSet
        tbl = ad.GetPagedEntityByUser(StartRowIndex, MaximumRows, UserID);
        //fill the strongly typed List with data
        foreach (ManageabilityDS.EntityRow row in tbl.Rows)
        {
            Entity en = new Entity();
            en.EntityID = row.EntityID;
            en.UserId = row.UserID;
            en.Title = row.Title;
            en.Description = row.Description;
            t.Add(en);
        }
        return t;
    }
    catch
    {
        throw;
    }
}

For the sorted:

/// <summary>
/// This function return a strongly type list containing paged and sorted data
/// </summary>
/// <param name="UserID"></param>
/// <param name="StartRowIndex"></param>
/// <param name="MaximumRows"></param>
/// <param name="ColumnToOrder"></param>
/// <param name="OrderDirection"></param>
/// <returns></returns>
public List<Entity> Select(string UserID, int StartRowIndex, int MaximumRows, string ColumnToOrder, string OrderDirection)
{
    ManageabilityDS.EntityDataTable tbl = null;
    List<Entity> t = new List<Entity>();
    try
    {
        ManageabilityDSTableAdapters.EntityTableAdapter ad = new ManageabilityDSTableAdapters.EntityTableAdapter();
        //GetPagedEntityByUserOrdered function is defined in the DataSet
        tbl = ad.GetPagedEntityByUserOrdered(StartRowIndex, MaximumRows, UserID, ColumnToOrder, OrderDirection);
        //fill the strongly typed List with data
        foreach (ManageabilityDS.EntityRow row in tbl.Rows)
        {
            Entity en = new Entity();
            en.EntityID = row.EntityID;
            en.UserId = row.UserID;
            en.Title = row.Title;
            en.Description = row.Description;
            t.Add(en);
        }
        return t;
    }
    catch
    {
        throw;
    }
}

 

Let's get back to the Presentation Layer. Here, as part of customization we have the
GridView inside a table which is sitting inside an asp:UpdatePanel... AJAX effect!!!
Simple, sweet and effective.

We had to create the PageLinks for navigation. The ellipsis and all other links are created
on the fly and provides smooth and fast navigation at any point.
When you click on the link, only PageSize number of rows are fetched from the database,
so practically it doesn't matter if you have 50K or 500K records!!!

Lets see how the Links are created:

/// <summary>
/// This sub creates all the links on the page
/// </summary>
private void CreateButtons()
{       
    int totalRecords = int.Parse(RecordCountHdn.Value);
    int pageSize = int.Parse(PageSizeHdn.Value);
 
    //calculate the total number of links to be created
    int totalPages = totalRecords % pageSize == 0 ? totalRecords / pageSize : (totalRecords / pageSize) + 1;
 
    //this is for the ellipsis, keeps a track of the previous bunch of links
    int x = int.Parse(ViewState["PageLinkLastBunchCount"].ToString());
 
    //its the counter that checks whether all the links are created
    int p = MAX_PAGE_LINKS * (x + 1);
    
    //The ellipsis linkbutton
    LinkButton ellipsis = null;
 
    ////To AJAXify the linkbuttons you need to have triggers
    AsyncPostBackTrigger t = null;
 
    //clear any previous links in the placeholder
    PageLinksPH.Controls.Clear();
 
    if (p < totalPages)
    {
        //if you are on the first bunch of links
        if (x == 0)
        {                
            for (int i = MAX_PAGE_LINKS * x; i < p; i++)
            {
                LinkButton l = new LinkButton();
                l.ID = "pagelink"+i;
                l.Text = string.Format("{0}", i + 1);
                l.ToolTip = string.Format("{0}+...", (i * pageSize) + 1);
                l.CommandArgument = string.Format("{0}", (i * pageSize) + 1);
                l.CssClass = "pagelink";
                //add event handler to each linkbutton
                l.Click += new EventHandler(l_Click);
                PageLinksPH.Controls.Add(l);
                t = new AsyncPostBackTrigger();
                t.ControlID = l.ID;
                AjaxPanel.Triggers.Add(t);
            }
            ellipsis = new LinkButton();
            ellipsis.ID = "ellipsisNext";
            ellipsis.Text = ">>";
            ellipsis.ToolTip = "Next";
            ellipsis.CommandArgument = string.Format("next");
            ellipsis.CssClass = "pagelink";
            //add event handler to each linkbutton
            ellipsis.Click += new EventHandler(ellipsis_Click);
            PageLinksPH.Controls.Add(ellipsis);
            t = new AsyncPostBackTrigger();
            t.ControlID = ellipsis.ID;
            AjaxPanel.Triggers.Add(t);
        }
        else //this will show next and the previous ellipsis
        {
            ellipsis = new LinkButton();
            ellipsis.Text = "<<";
            ellipsis.ID = "ellipsisPrevious";
            ellipsis.ToolTip = "Previous";
            ellipsis.CommandArgument = string.Format("previous");
            ellipsis.CssClass = "pagelink";
            //add event handler to each linkbutton
            ellipsis.Click += new EventHandler(ellipsis_Click);
            PageLinksPH.Controls.Add(ellipsis);
            t = new AsyncPostBackTrigger();
            t.ControlID = ellipsis.ID;
            AjaxPanel.Triggers.Add(t);
            for (int i = MAX_PAGE_LINKS * x; i < p; i++)
            {
                LinkButton l = new LinkButton();
                l.ID = "pagelink" + i;
                l.Text = string.Format("{0}", i + 1);
                l.ToolTip = string.Format("{0}+...", (i * pageSize) + 1);
                l.CommandArgument = string.Format("{0}", (i * pageSize) + 1);
                l.CssClass = "pagelink";
                //add event handler to each linkbutton
                l.Click += new EventHandler(l_Click);
                PageLinksPH.Controls.Add(l);
                t = new AsyncPostBackTrigger();
                t.ControlID = l.ID;
                AjaxPanel.Triggers.Add(t);
            }
            ellipsis = new LinkButton();
            ellipsis.ID = "ellipsisNext";
            ellipsis.Text = ">>";
            ellipsis.ToolTip = "Next";
            ellipsis.CommandArgument = string.Format("next");
            ellipsis.CssClass = "pagelink";
            //add event handler to each linkbutton
            ellipsis.Click += new EventHandler(ellipsis_Click);
            PageLinksPH.Controls.Add(ellipsis);
            t = new AsyncPostBackTrigger();
            t.ControlID = ellipsis.ID;
            AjaxPanel.Triggers.Add(t);
        }
    }        
}

Event handler for the ellipsis:

/// <summary>
/// The ellipsis' event handler. It shows the next/previous bunch of links
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ellipsis_Click(object sender, EventArgs e)
{
    //throw new Exception("The method or operation is not implemented.");
    LinkButton l = (LinkButton)sender;
    int x = int.Parse(ViewState["PageLinkLastBunchCount"].ToString());
    if (l.CommandArgument.ToLower().Equals("previous"))
    {            
        x--;
    }
    else if (l.CommandArgument.ToLower().Equals("next"))
    {
        x++;        
    }
    ViewState["PageLinkLastBunchCount"] = x;
    CreateButtons();
}

Event handler for the links:

/// <summary>
/// This handler will send the query to the database fetching the 
/// exact number of records only. It also takes care of sorting.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void l_Click(object sender, EventArgs e)
{
    //throw new Exception("The method or operation is not implemented.");
    //Response.Write("l_Click");
    try
    {
        LinkButton l = (LinkButton)sender;
        l.CssClass = "pagelinkSelected";
        int startIndex = int.Parse(l.CommandArgument);
        ViewState["PageStartIndex"] = startIndex;
        int pageSize = int.Parse(PageSizeHdn.Value);
        using (Entity en = new Entity())
        {
            if (_isPageSorted)
            {
                MainGrid.DataSource = en.Select(_userID, startIndex, pageSize, ColumnList.SelectedValue.ToString(), OrderDirectionList.SelectedValue.ToString());
            }
            else
            {
                MainGrid.DataSource = en.Select(_userID, startIndex, pageSize);
            }
            MainGrid.DataBind();
        }
        InfoLabel.Text = string.Format("You are at Page# {0}", l.Text);
    }
    catch(Exception ex)
    {
        ErrorLabel.Text = ex.Message;
    }
}

After you follow the steps above, I am sure it will be a cake walk for you all to create
or maintain any such page. It might appear to be lots of work, but its highly reliable
and scalable. No blackboxes!!!

So, this brings us to an end of this long post, I sincerely hope it will help you a lot.

See you soon...

Calling a ASP.Net 2.0 Webservice from an XBAP

Today, I was trying out a couple of things with WPF. Here is the scenario:
I created a simple XML file called "People.xml". My objective was to use this file as a database for my first data aware XBAP.
I had a lot of problems making it to work. The reason?
  • It actually tries to find the file in system32 folder
  • I couldn't figure out a way to send that file as part of deployment process.
  • This is actually a bad idea. Having local copies of database? nah...

The best idea is to have a WebService that acts as your business/data access layer.
This actually gives you a centralized database. So, I didn't break my head further and moved ahead implementing
the WebService solution. This solution also required a lot of brainstorming and troubleshooting.
We always used to get "Trust Not Granted" when we used "This is a Full Trust application".

When we used partial trust, it would fail with "System.Security.SecurityException"

Request for the permission on type System.Net.webPermission failed.

 
Problem, problem... never mind... there has to be a solution.
 
When we used a custom security settings for the ClickOnce deployment we got "Trust Not Granted".
 
The resolution to this problem is to install the temporary security certificate that is created by default in the XAML browser application. Its named in the format: <ApplicationMane>_TemporaryKey.pfx

You need to install this certificate at the client machines where the application is supposed to run, under Trusted Root Certificate and Trusted Publishers zone.

Once done, you can also use a Full Trust ClickOnce deployment.

Enjoy XBAP.

Posted by Sanjeet | 1 Comments

There is something about Delegates

Whenever you might have started reading about Delegates, the first line you read is : "Delegates are function pointers in C#"

Now what is a function pointer? and how is it going to make my life any easier?

Lets understand function pointers now.

Function Pointers

In old C++ days, we used pointers. We do not use it anymore in our .Net managed world. Atleast all those people who use the luxary of Visual Studio don't.

A pointer is declared as:  

1: int* p = &x;   
2: // this actually allocates a block of memory of size 4 bytes
3: // to store the address in memory of the variable x.   
4: // I would like to mention that each memory allocation has an address attached to it.   
5: // even this ponter thing has got an address in memory.    
6: // So the following line of code is perfectly legal.   
7: int** p2p = &p;
 
The Function pointer is implemented as following in C++
   
1: // lets create a simple function   
2: int Add2Numbers(int i, int j)   
3: {   
4:     return i+j;   
5: }   
6: // So far so good, no flashy stuff!   
7: // Now lets call this function   
8: int x = Add2Numbers(2,5);   
9: // So what, I have been using this since ages.  
10: // Agreed, try this:  
11: int (*p2F)(int, int) = &Add2Numbers;  
12: int x = p2F(2, 5); // returns 7  
13: // Oops, what was that?  
14: // Here, p2F is a pointer to the function Add2Numbers.   
 
 
So, whats the point?
  • You have a neater construct to call functions. You can call Add2Numbers, and Sub2Numbers by using other means like a "Switch", based upon user selection.
  • You are making calls by reference, it is considered faster than calling by value, also you make changes to the same data. You do not make copies, no redundancy issues. Works, doesn't it?

Delegates in C#

You will be glad to know that in our managed world, everything is managed ! Alright.... just trying to be funny.

An integral part of being managed is to be able to know in advance what you are going to do. It holds good for Delegates also.

So, unlike C++ where you can assign a pointer with whatever function you wish, we have "invented" Delegates. So, just like you declare an int, or a business object, you need to declare a Delegate. Our runtime now knows what you plan to do. No surprises at runtime please. If you offer surprises, be ready to be surprised by the runtime. You get in return at execution what you throw at it at design time. This is cool stuff, isn't it?

I am pretty sure, you now know the whereabouts of what I am talking right now. We use Delegates so that we can call functions/methods based on the requirements of the program in execution. It is defined for all methods/functions that match a given signature. But, you need to provide it with the function/method name. So, the complier still knows your intentions.

Let me share some features now:

  • They 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.
  • A delegate declaration defines a type that encapsulates a method with a particular set of arguments and return type.

Getting bored? Don't worry, let my code do the talking...

/// <summary>
    /// A separate class that contains delegates and functions
    /// </summary>
    public class MyDelClass
    {
        /// <summary>
        /// This delegate can be a pointer to all functions that doesnt have any return value and any args
        /// </summary>
        public delegate void NoReturn_And_NoArgDel();
 
        /// <summary>
        /// This delegate can be a pointer to all functions that has a return value but no args
        /// </summary>
        /// <returns></returns>
        public delegate string Return_But_NoArgDel();
 
        /// <summary>
        /// This delegate can be a pointer to all functions that has return value and args also
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        public delegate string Return_And_ArgDel(string arg);
 
        /// <summary>
        /// Constructor of the class
        /// </summary>
        public MyDelClass() { }
 
        /// <summary>
        /// A simple HelloWorld function that doesnt return a value or take any arg
        /// </summary>
        public void HelloWorld()
        {
            Console.WriteLine("Hello World");
        }
 
        /// <summary>
        /// A simple HelloWorld function that returns a value but takes no arg
        /// </summary>
        /// <returns></returns>
        public string HelloWorldReturns()
        {
            return "Hello World Returns";
        }
 
        /// <summary>
        /// A simple HelloWorld function that returns a value and takes an arg
        /// </summary>
        /// <returns></returns>
        public string HelloWorldReturns(string arg)
        {
            return arg;
        }
 
    }

Points to be noticed:

The signature:

public delegate return_type delegate_name(arg_list)

ensures that the runtime knows in advance the type of your delegate. This ensures type safety.

Delegate is a sealed class. You can't inherit from it. So, its secure.

Now lets see what the entry point function has got for us:

class Program
{
    static void Main(string[] args)
    {
        //instantiate the class
        MyDelClass myDel = new MyDelClass();
 
        //First delegate
        MyDelClass.NoReturn_And_NoArgDel delNoReturnNoArg = new MyDelClass.NoReturn_And_NoArgDel(myDel.HelloWorld);
        delNoReturnNoArg.Invoke();
 
        MyDelClass.Return_And_ArgDel delReturnAndArg = new MyDelClass.Return_And_ArgDel(myDel.HelloWorldReturns);
        Console.WriteLine(delReturnAndArg.Invoke("Hello World from function Main()"));
 
        MyDelClass.Return_But_NoArgDel delReturnButNoArg = new MyDelClass.Return_But_NoArgDel(myDel.HelloWorldReturns);
        Console.WriteLine(delReturnButNoArg.Invoke());
 
        Console.Read();
    }
}
 
A delegate is an attribute of the class not of its instance.
You need to use the Invoke() method of the instance of the delegate to call your methods encapsulated by the delegate synchronously.
 
MyDelClass.NoReturn_And_NoArgDel delNoReturnNoArg = 
new MyDelClass.NoReturn_And_NoArgDel(myDel.HelloWorld);
 
Its possible for your delegates to call more than one function at a time:
 
MyDelClass.NoReturn_And_NoArgDel delNoReturnNoArg = 
new MyDelClass.NoReturn_And_NoArgDel(myDel.HelloWorld);
 
delNoReturnNoArg += 
new MyDelClass.NoReturn_And_NoArgDel(myDel.HelloWorld2);
 
So, you can have more than one method hooked to a delegate.
 
public delegate void d(string one); 
d a = new d1(FuncOne);
a.Invoke("1");
d b = new d2(FuncOne);
b.Invoke("2");
d x = a + b;
x.Invoke("3"); 
// Result: 1233
private void FuncOne(string one)
{
    Console.Write(one);
}
 
Posted by Sanjeet | 3 Comments

AJAX in a nutshell : It can't get any simpler folks

1. Ajax basics

- "Asynchronous JavaScript and XML," is a web development technique for creating interactive web applications. The intent is to make web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user requests a change.

- Ajax uses the following existing technologies.
Designing/Styling : XHTML/HTML, CSS
Async/Sync calls to the server : XMLHttpRequest
Data manipulation : DOM
Data Exchange : XML, Html, Plain Text, JSON

- Ajax is not a technology in itself, but a term that refers to the use of a group of technologies.

2. History

- Although the term Ajax was coined in 2005, most of the technologies that enable Ajax started a decade earlier with Microsoft's initiatives in developing Remote Scripting.

- AJAX was made popular in 2005 by Google (with Google Suggest).

- Remote Scripting allowed a Java Applet to pull data from the server and then use JavaScript at the client side to manipulate it.

- Microsoft then introduced XMLHttpRequest object in IE5 and used it extensively in OWA and MS Exchange 2000.

3. Advantages

- User Experience
- Bandwidth Usage
- Separation of Data, format, style and function

4. Disadvantages

- Browser Integration
The dynamically created page does not register itself with the browser history engine, so triggering the "Back" function of the users' browser might not
bring the desired result.
Another issue is that dynamic web page updates make it difficult for a user to bookmark a particular state of the application.

- Response Time
Network Latency or the interval between user request and server response - needs to be considered carefully during Ajax development. ASP.Net Ajax has UpdateProgress to counter this concern.

- Dependency on Javascript
Ajax relies on JavaScript, which may be implemented differently by different browsers or versions of a particular browser.

5. A quick view of XMLHttpRequest

- http://blogs.msdn.com/sanjeets/archive/2007/04/11/xmlhttp-step-1.aspx
- http://blogs.msdn.com/sanjeets/archive/2007/04/13/xmlhttp-step-2.aspx

6. Ajax Toolkit and CTP

- You need important AJAX Downloads to get started. It contains the AJAX Toolkit and Community Technology Preview controls.

- The AJAX Extensions provides you with all the necessary controls like UpdatePanel, UpdateProgress, ScriptManager etc. It also provides you with an ASP.Net AJAX Enabled Website template. It is installed in your Visual Studio 2005. So, all you need to do is to select this template and then rock and roll.

- The AJAX Toolkit is a set of controls that greatly enhance the UI and provides easy to use functionality.

- The CTP tools provide you an some original and extender controls. This is actually created and supported by the ASP.Net AJAX community.

- See the ASP.Net AJAX videos to do simple things simply

7. Asynchronous communication Layer

- The MS ASP.Net AJAX Asynchronous Communication Layer enables a browser to call a Web Service method on the server using Javascript.

- It exposes APIs that Javascript functions can use in any browser to call Webservice.

- It can invoke ASP.Net page methods.

- It supports a variety of serialization formats like JSON(Javascript Object Notation), string, and XML.

- Generates JavaScript proxies at the client so that methods can be accessed using XMLHttp.

- It provides a default XMLHttpExecutor class that functions as an interface between a client web request and the network.

- The ASP.Net AJAX Client Asynchronous Communication Layer looks like following. It uses JSON for data exchange by default. Its preferred over SOAP/XML because of it doesn't need to use extensive Javascript to construct requests.

- The proxies are created at the client end. This facilitates XMLHttpRequest object to send requests.

- The Server Asynchronous Communication Layer looks like following. The Http Handler performs deserialization of JSON/XML request and hands it over to Business classes.

8. ScriptManager

- This guy needs special introduction as it sits on each of your AJAX enabled page.

- By default, the ScriptManager control registers the script for the Microsoft AJAX Library with the page. This enables client script to use the type system extensions and to support features such as partial-page rendering and Web-service calls.

- It enables Client-script functionality of the Microsoft AJAX Library, and any custom script that you want to send to the browser.

- Partial-page rendering, which enables regions on the page to be independently refreshed without a postback. The UpdatePanel, UpdateProgress and Time controls need it.

- JavaScript proxy classes for Web services, which enable you to use client script to access Web services by exposing Web services as strongly typed objects.

9. Resources
-
http://en.wikipedia.org/wiki/AJAX
- http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/aboutxmlhttp.asp

Posted by Sanjeet | 1 Comments
Filed under:

There's something about Async - 1

An overview of Asynchronous-ness:

Getting started

You must have read in a number of blogs/articles that asynchronous operations are good for your UI responsiveness. It sounds good too. But, for last many months I have been working hard to put them in place so that I can actually understand and use them. Finally, I did manage to understand.

You are lucky to be reading this, as I will give you what most articles fail to deliver - simplicity. Too much information is not good. So, let's live one concept at a time. We will try to keep it short and direct. So, let's rock and roll.

Checklist:

Before we start to cook anything, we need the ingredients. Here are they:

  • Delegates : Don't worry they are not so scary.
  • Threads and threading : I know these are a little complicated stuff, but you need to understand them. You can count on me; I will not make hot gravy.
Posted by Sanjeet | 1 Comments

XMLHttp : Step 2

How to call Webserver methods using Javascript

 

If you are planning to call your own ASP.Net webservice from client side using XMLHttp you need to configure its web.config.

Add the following inside <system.web>:

<webservices>
  <protocols>
    <add name="HttpPost">
    <add name="HttpGet">
  </protocols>
</webservices>

Paste the following in your htm page. This, however, requires you to fine tune according to your setup. I am using the default namespaces for the XML SOAP header, and my webservice resides on one of my servers.

<html>
<head>
<script language="javascript">

//Instantiated an XMLHTTP object.

var xmlRequest = new ActiveXObject("MSXML2.XMLHTTP");

//The following is the event handler for the object.

function OnComplete()
{
var spn = document.getElementById("ContentSpan");

//object.readyState gives us the current status of the async operation. The meaning of status code is printed on the page using the innerHTML property of span. e.g. readyState value 1 corresponds to an open connection.


switch(xmlRequest.readyState){
case 1:
spn.innerHTML = "connection opened."
break;
case 2:
spn.innerHTML += "<br>POST request sent."
break;
case 3:
spn.innerHTML += "<br>recieving data...<br>"
break;
case 4:
var responseXML = xmlRequest.responseText;
spn.innerHTML += responseXML;
alert("Length of response = " + responseXML.length);
spn.innerHTML += "<br>complete."
break;
}
}

//The following is actually the handling the onClick event for the button.

function Invoke_Click()
{

//The following creates a SOAP header for the request.


var soapEnvelope = "<soap:Envelope xmlns:xsi=\"
http://www.w3.org/2001/XMLSchema-instance\""
soapEnvelope += " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
soapEnvelope += " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
soapEnvelope += "<soap:Body>"
soapEnvelope += " <About xmlns=\"
http://tempuri.org/\" />"
soapEnvelope += "</soap:Body>"
soapEnvelope += "</soap:Envelope>"

//Assign OnComplete handler to onreadystatechanged. This handler asynchronously gives the status of the response.


xmlRequest.onreadystatechange = OnComplete;

//Open the connection, send a POST request to the Webservice. The "true" parameter marks that an async request is sent.


xmlRequest.open("POST", "
http://sanjeets-2k3/LogParserWS/LogParserService.asmx/HelloWorld", true);
try{

//The Content-Type needs to be set to text/xml


xmlRequest.setRequestHeader("Content-Type", "text/xml");

//Use the send method to send the request. You can also add the request header that we created above. Although its optional.
xmlRequest.send(soapEnvelope);
}
catch(e){
alert(e.message);
}
}

</script>

</head>
<body>

//A simple HTML button.

<input type="button" id="InvokeButton" value="Invoke" onclick="Invoke_Click();" />
<br />

//A span to write the response HTML.


<span id="ContentSpan"></span>
</body>
</html>

Posted by Sanjeet | 2 Comments
Filed under: ,
More Posts Next page »
 
Page view tracker