Friday, December 31, 2010

Search a text in all properties of an object in collection (FullTextSearch) using LINQ

Recently in our project, we had a requirement to search for particular character in the List. The search is similar to FullTextSearch which means, we need to search for a specific character in each and every property of an object contained in the list..
We initial thought the only way is to use LINQ to add condition for every property with OR statement. Then while googling got one idea from this link;
http://manfred-ramoser.blogspot.com/2009/09/full-text-search-for-entity-framework.html

This exactly does the same what we needed except failed in one scenario. (i.e.) this failed when any of the property is NULL. So I modified the code a little bit which take cares of the NULL situation as well. Below is that code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;


namespace TestXML
{
public static class QuerableExtensionMethods
{
public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> querytable, string searchkey)
{
return FullTextSearch<T>(querytable.AsQueryable<T>(), searchkey, false);
}


public static IQueryable<T> FullTextSearch<T>(this IQueryable<T> querytable, string searchkey,bool exactMatch)
{


ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
ParameterExpression stringParameter = Expression.Parameter(typeof(string), "d");
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
MethodInfo nullMethod = typeof(string).GetMethod("IsNullOrEmpty", new Type[] { typeof(string) });
var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(p => p.PropertyType == typeof(string));
Expression orExpression = null;


string[] searchKeyParts = null;


if (exactMatch)
searchKeyParts = new[] { searchkey };
else
searchKeyParts = searchkey.Split(' ');


foreach (var property in publicProperties)
{
Expression nameProperty = Expression.Property(parameter, property);
foreach (var searchKeyPart in searchKeyParts)
{


Expression searchkeyExpression = Expression.Constant(searchKeyPart);
Expression nullCheckExpression = Expression.Constant(null);
Expression callContainsMethod = Expression.Call(nameProperty, containsMethod, searchkeyExpression);
Expression nullCheckMethod = Expression.Call(stringParameter, nullMethod, nameProperty);
Expression notExpression = Expression.Not(nullCheckMethod);


if (orExpression == null)
orExpression = Expression.AndAlso(notExpression, callContainsMethod);
else
orExpression = Expression.Or(orExpression, Expression.AndAlso(notExpression, callContainsMethod));
}
}
MethodCallExpression whereCallExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { querytable.ElementType }, querytable.Expression,
Expression.Lambda<Func<T, bool>>(orExpression, new ParameterExpression[] { parameter }));


return querytable.Provider.CreateQuery<T>(whereCallExpression);
}


}
}

Happy coding and wishing all the viewers of my blog happy and prosperous new year!!!!

Wednesday, December 15, 2010

Counter-Queue and Counter-Wait Pool Patterns for SaaS Implementations

SaaS or Software as a Service is the upcoming paradigm shift in the IT industry. Everyone is shifting towards converting their offerings to Cloud platforms. Some of the key things in this model are the; 
  • Effective utilization of the resources available
  • Satisfy as much service requests as possible with the available resources
  • High Throughput

 The Counter-Queue Pattern is an attempt to increase the productivity of the SaaS offerings using the real life scenario of Ticket booking counters in the Railways Stations. Like in the booking counters, the service requests will be piled up in the queues available and executed in parallel. Say we plan to have 10 queues; the service requests available in the 10 queues will be executed in parallel. The diagram below pictorially explains the Counter-Queue pattern;

  1. Initially, the service requests will be put in the “Input Queue”
  2. The queue manager reads the service requests in the “Input Queue” and allocates them to the “Counter Queues” available. Each counter queue will have the max queue size, depending on that, the queue manager allocates the service requests in them
  3. Each counter will perform the similar functionality. They will pick up the service requests in their respective counter queues and perform the necessary functionality and put the result in the “Output Queue”

In case, any counter fails; the service requests will be moved back to the end of the “Input Queue” for re-allotment. As you can notice, the problem here is that when any counter fails; SLA of the service requests in those queues will not be met.

The “Counter-Wait Pool pattern” will solve this problem. The below diagram pictorially explains this pattern


  1. Initially, the service requests will be piled up in the input queue
  2. The queue manager picks the service requests from the “Input Queue” and assigns a sequential number to it and put in the wait pool. There will be a max size set to the wait pool. Depending on that, queue manager will put the service requests in the wait pool.
  3. Each counter will have “Next token” display in them. Depending on the number displayed, the service requests will be picked from the wait pool.
  4. Once the counter services the request, the result will be put in the “Output Queue”.

As you can notice, here we will not run into the problem of not meeting the SLA of the service requests on any scenario 

Monday, December 13, 2010

Forbidden 403 error while accessing workitems in TFS2010 sharepoint site Dashboard

Sometimes you may experience the "Forbidden 403" error in TFS2010 when you try to access the workitems from Dashboard in Sharepoint site.

Here is the solution for that;
1) Login to the TFS Application server
2) Locate the directory "C:\inetpub\wwwroot\bin"
3) Give Write permission for the users of TFS

Bingo, now you should be able to access workitems from Dashboard.

Tuesday, November 9, 2010

Abstract Factory pattern in simple terms

Just tried out abstract factory pattern... One of my colleague had issues coming up with the pattern.. Just helped him with the sample below;

Invocation point:
var obj = FactoryManager.GetFactory(1);

Implementation:

namespace ConsoleApplication2
{
    internal class RootDO
    {

    }

    internal sealed class SubDO1 : RootDO
    {

    }

    internal sealed class SubDO2 : RootDO
    {

    }

    internal abstract class RootClass<T> where T: RootDO ,new ()
    {

    }

    internal sealed class SubClass1<T> : RootClass<T> where T: RootDO,new ()
    {

    }

    internal sealed class SubClass2<T> : RootClass<T> where T: RootDO, new ()
    {

    }
    internal interface IFactory<S, T>
    {
         S GetObject();
    }

    internal class SubClass1Factory : IFactory<SubClass1<SubDO1>,SubDO1>
    {
        public SubClass1<SubDO1> GetObject()
        {
            return new SubClass1<SubDO1>();
        }

        internal static SubClass1<SubDO1> GetFactory()
        {
            SubClass1Factory s = new SubClass1Factory();
            return s.GetObject();
        }
    }

    public class FactoryManager
    {
        public static object GetFactory(int type)
        {
            return SubClass1Factory.GetFactory();
        }
    }
}
 



Monday, November 8, 2010

TFS2010 Team build automation - workaround


The builds in TFS2010 will work smoothly for .NET 4.0 and even .NET 3.5, .NET 2.0 solutions. But there is a catch here. The build of solutions in .NET 3.5 and below will fail with the issue saying “GenerateResource task failed unexpectedly..… FileTracker.dll missing….” when they have resource files.
This is the known issue in TFS2010. Microsoft tried to introduce a new concept of Incremental builds in TFS2010. This has caused this known issue.

The solution is to add "TrackFileAccess = false" in the GenerateResource task. This is the work around suggested by Microsoft. 
But, what to do if need to enable the build of Setup & Deployment projects? MSBuild do not support the build of .vdproj files which are nothing but setup & deployment projects. So to enable this, we need to call devenv.exe process to do this. But “TrackFileAccess” property is not supported in .NET 3.5 Microsoft.Common.tasks.dll and we will get build error :(

To solve both these issues, the following is the approach which can be helpful.

1) Go to the .NET 3.5 framework folder in the build server box
 
2) Locate the Microsoft.Common.targets file. Copy-Paste this file and rename to Microsoft.Common.targets.CSharp

3) Open the file “Microsoft.Common.targets.CSharp” and locate the “GenerateResource” task in the file. Add the attribute “TrackFileAccess = false” in there as shown below


4) Locate the files “Microsoft.CSharp.targets” and “Microsoft.VisualBasic.targets” files and update the “Import” tag as shown below

“Microsoft.CSharp.targets” file is for C#.NET builds and “Microsoft.VisualBasic.targets” file is for VB.NET builds
5)  Adding the MS Build arguments
a.    Go to TFS Builds
b.    Select the build
c.    Edit build definition and then go to “Process” section
d.    Expand “Advanced” build process parameters
e.    Locate “MS Build Arguments”
f.    Add this statement “/p:CSharp=.CSharp”





Bingo!!! That’s it. Now we are ready to build any .NET 3.5 solutions without any issues

 what actually we are trying to do here is, whenever we initiate team build, we are passing the value for MSBuild argument "$(CSharp)", so the imported file will be Microsoft.Common.targets.CSharp which contain TrackFileAccess = false property in GenerateResource task. When we build the solution using devenv.com or devenv.exe commands, we don's pass the value for that MSBuild argument which in turn import the file Microsoft.Common.targets which do not contain TrackFileAcess property in GenerateResource task.