Thursday, June 16, 2016

Data Caching in a WPF


In this article I will explain how you can cache object in memory in WPF application to get better performance.

Cached data will be stored in memory so you will get faster access to that data compare to accessing it from File or Database. So whenever you need to make frequent calls to some database or file, better you cache that data and read from cached object this will improve your application performance via reducing multiple calls to database or file.

Caching mechanism provided by .Net framework 4.0. Caching is available under System.Runtime.Caching namespace and you need to add this namespace in your project references.  

See below example, where multiple calls are being made to database for getting employee details based on employee name.

XAML - 
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <TextBlock Text="Name of employee - " HorizontalAlignment="Center"
               VerticalAlignment="Center"
                Grid.Row="0" Grid.Column="0" />
    <TextBox Name="EmpName" VerticalContentAlignment="Center"
             Text="{Binding Path=EmployeeName, Mode=TwoWay}"
                Height="30" Width="150" HorizontalAlignment="Center"
                VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" />
    <Button Name="Search" Content="Search" Click="Search_Click"
            Grid.Row="0" Grid.Column="2" Height="30" Width="150" />
    <ListBox Height="200" Width="200" Name="EmployeeList"
                ItemsSource="{Binding}" Grid.Row="1" Grid.Column="0"
                Grid.ColumnSpan="3" />
</Grid>

Code –
public partial class MainWindow : Window
{
    ObservableCollection<string> Employees = new ObservableCollection<string>();
    public MainWindow()
    {
        InitializeComponent();
    }
    //Search Button event handler
    private void Search_Click(object sender, RoutedEventArgs e)
    {
        Employees = GetEmployeesByName(EmpName.Text);
        this.DataContext = Employees;
    }
    //Make calls to database to get employee details based on given name
    private ObservableCollection<string> GetEmployeesByName(string name)
    {
        ObservableCollection<string> employeeNames = new ObservableCollection<string>();
        string connectionString = "Data Source=MITESH-PC\\SQLEXPRESS;Initial Catalog=TestSQLDB;Integrated Security=SSPI";
        using (SqlConnection sqlConnection = new SqlConnection(connectionString))
        {
            string cmd = "select firstname + ' ' + lastname as [EmployeeName] from HR.Employees where firstname like @FirstName";
            SqlCommand command = new SqlCommand(cmd, sqlConnection);
            command.Parameters.Add(new SqlParameter("@FirstName", name));
            sqlConnection.Open();
            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    employeeNames.Add(reader["EmployeeName"].ToString());
                }
            }
            sqlConnection.Close();
        }
        return employeeNames;
    }
}


Output – 



In above example, for each employee search is costing database call. To avoid database call for each employee, we can cache all employee name at once and for each subsequent search we can get it from cached object. This will reduce database call every time we search on employee and increase performance. See below code which implements caching.

Code –
public partial class MainWindow : Window
{
    ObservableCollection<string> Employees = new ObservableCollection<string>();
    //cache object
    ObjectCache cache = MemoryCache.Default;
    public MainWindow()
    {
        InitializeComponent();
        //Gets all employess from database
        Employees = GetAllEmployees();
        //sets employees in cache
        cache.Set("AllEmployees",Employees, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5) });
    }
    //Search Button event handler
    private void Search_Click(object sender, RoutedEventArgs e)
    {
        //Get employeelist from cached object
        ObservableCollection<string> employeeList =  cache["AllEmployees"] as ObservableCollection<string>;
        //if cache is expired or no object available in cache then set cache object again
        if (employeeList == null)
        {
            employeeList = GetAllEmployees();
            cache.Set("AllEmployees", Employees, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5) });
        }
        //search employee name from employee list loaded from cache object
        var selecteEmployees = (from emp in Employees
                                where emp.ToLower().Contains(EmpName.Text.ToLower())
                                select emp).ToList();
        this.DataContext = selecteEmployees;
    }
    //Gets all employess from database
    private ObservableCollection<string> GetAllEmployees()
    {
        ObservableCollection<string> employeeNames = new ObservableCollection<string>();
        string connectionString = "Data Source=MITESH-PC\\SQLEXPRESS;Initial Catalog=TestSQLDB;Integrated Security=SSPI";
        using (SqlConnection sqlConnection = new SqlConnection(connectionString))
        {
            string cmd = "select firstname + ' ' + lastname as [EmployeeName] from HR.Employees";
            SqlCommand command = new SqlCommand(cmd, sqlConnection);
            sqlConnection.Open();
            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    employeeNames.Add(reader["EmployeeName"].ToString());
                }
            }
            sqlConnection.Close();
        }
        return employeeNames;
    }
}

Output – 


Output is same as above example, but in this example In-Memory caching is being used. In constructor, I loaded all the employees from database and added to the cache object. When every time user search for employee, search will be perform on in memory object and result will be returned. In this example cache expiry is set to 5 minutes but you can set as per your need. After every 5-minute cache object will get expired and employee list will be null. After cache expired, if you still need cached object then you need to load it again from database or file and add to cache again.

In memory caching is very beneficial and recommended for applications which are making multiple calls to database, file system or others. You can set cache expiry time if you want to delete or update or refresh cache object after certain time. Caching will improve performance and scalability of your application.

Hope this article helps you to understand how to cache data objects in WPF application. Please leave your feedback in comments below.


References –

See Also –


Saturday, June 11, 2016

Prototype Pattern


Prototype pattern is used to create an object from exiting object via cloning. Prototype pattern falls under creational pattern of GOF (Gang of Four) pattern.

When to use –


When you want to create an object by copying it from other object or prototype. So prototype act as master or blueprint and other objects created from master object are copies of that object. In short, Prototype pattern is used to clone objects. In real world example, a photocopy machine creates multiple copies from original document and you can independently use or send photocopies wherever you want to use original document.

Major components of prototype pattern are –


  • Prototype It’s an interface for cloning.
  • Concrete Prototype – Implements prototype interface and clone itself.
  • Client – Creates new object and ask to create clone of created object.

Prototype pattern is easy to implement. You can create your own interface which contains Clone method and use it as prototype. In below example I used ICloneable interface as Prototype.

Code –
public class Address
{
    public string Line1 { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public override string ToString()
    {
        return string.Format("Line1 : {0}, City : {1}, Country : {2}", Line1, City, Country);
    }
}
//ConcretePrototype
public class Person : ICloneable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
    public object Clone()
    {
        return this.MemberwiseClone();
    }
    public override string ToString()
    {
        return string.Format("Name : {0}, Age : {1}, Address : {2}", Name, Age, Address.ToString());
    }
}
//Client
class Program
{
    static void Main(string[] args)
    {
        //New Person object
        Person p1 = new Person() { Name = "Mitesh", Age = 30, Address = new Address() { Line1 = "Addr 1", City = "Pune", Country = "India" } };
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        //Clone person object from existing P1 object
        Person p2 = (Person)p1.Clone();
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        //Modify P2 object
        p2.Name = "John";
        p2.Age = 40;
        p2.Address.Line1 = "A1";
        p2.Address.City = "Atlanta";
        p2.Address.Country = "USA";
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        Console.ReadLine();
    }
}


Output –




In above example, I used MemberwiseClone () method which is available to all objects. This method creates shallow copy of an object. This method copies the values of all the fields and doesn’t copy references in the object points to. When object is simple and doesn’t contain any references of other objects then this method works very well. In above example I changed address of P2 object then it has also changed address of P1 object as well and this is not expected when you clone an object. To solve this problem, we need to use deep copy functionality to copy an object. See below example with little change in Clone method to implement deep copy.

Code –
public class Address
{
    public string Line1 { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public override string ToString()
    {
        return string.Format("Line1 : {0}, City : {1}, Country : {2}", Line1, City, Country);
    }
}
//ConcretePrototype
public class Person : ICloneable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
    public object Clone()
    {
        //Shallow copy
        Person obj =  (Person)this.MemberwiseClone();
        //Deep copy
        obj.Address = new Address() { Line1 = this.Address.Line1, City = this.Address.City, Country = this.Address.Country };
        return obj;
    }
    public override string ToString()
    {
        return string.Format("Name : {0}, Age : {1}, Address : {2}", Name, Age, Address.ToString());
    }
}
//Client
class Program
{
    static void Main(string[] args)
    {
        //New Person object
        Person p1 = new Person() { Name = "Mitesh", Age = 30, Address = new Address() { Line1 = "Addr 1", City = "Pune", Country = "India" } };
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        //Clone person object from existing P1 object
        Person p2 = (Person)p1.Clone();
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        //Modify P2 object
        p2.Name = "John";
        p2.Age = 40;
        p2.Address.Line1 = "A1";
        p2.Address.City = "Atlanta";
        p2.Address.Country = "USA";
        Console.WriteLine("---------P1-----------");
        Console.WriteLine(p1.ToString());
        Console.WriteLine("---------P2-----------");
        Console.WriteLine(p2.ToString());
        Console.ReadLine();
    }
}

Output –











As you can see in above example, I made changes in Clone method and implemented deep copy functionality to copy reference object along with other values of object. Now you can see there is no change in P1 object’s address after changing P2 object’s address. It means implementing deep copy in prototype pattern we get brand new P2 object from prototype which has no relation with P1 object.

Difference between shallow copy and deep copy –


Shallow Copy
Deep Copy
Copies value types from source object to target object. It also copies object’s reference type as reference but not the referenced object itself.
Deep copy makes a complete copy of value types and reference types with actually coping it’s reference object.
Shallow copy objects are not 100% disconnected to its original object.
Deep copy objects are 100% disconnected to its original object.
MemeberwiseClone() method used to create Shallow copy of an object.
Need to override Clone method to modify object returned from MemeberwiseClone() to copy actual reference types.
Shallow copy is fast and less expensive
Deep copy is slow and expensive compare to shallow copy.
Shallow copy preferred when object has primitive types.
Deep copy is preferred when object has references to other objects.


Hope this article helps you to understand Prototype Pattern. Please leave your feedback in comments below.

References –

See Also –