Sunday, February 13, 2011

Entity Framework 4.0 Repository Factory Pattern

In this post I am going to show you how to write some clean code using a repository pattern and entity framework for data access. I am also using the UnitOfWork pattern and Specification pattern. One thing to note is that EF 4.0 provides us with an Out of the box UnitOfWork called ObjectContext (in my case I am using another level of abstraction on top of that). First, I need to think in terms of blue prints and how to design a well formed skeletton that is decoupled and that makes room for flexibility and testability. For demo puposes, I am just gonna pick out one scenario..So, i need a bridge class that i call a 'Pipe' which is going to act as a data bridge between the presentation layer and the repositories, and the repositories would then talk to the entity framework. Let's start by looking at how the business facade looks like where the 'Pipe' lives.

   1:  public class PhysicianPipe : IPhysicianPipe
   2:  {
   3:          IRepositoryGarden repositoryGarden;
   4:          public PhysicianPipe(IRepositoryGarden RepositoryGarden)
   5:          {
   6:              repositoryGarden = RepositoryGarden;
   7:          }
   8:   
   9:          public void AddPhysician(Domain.Entities.Physician physician)
  10:          {
  11:              repositoryGarden.PhysicianRepository.Add(physician);
  12:              repositoryGarden.SaveRepositoryChanges();
  13:          }
  14:  }

Basically I handed over the UnitOfWork responsibility to the repository garden where it gets injected in the constructor, that way i can use an IoC container (StructureMap, Unity, Ninject, etc..) and can configure it to inject a real UnitOfWork or a Fake one for testing purposes. We'll look at how the repository garden (this acts as a repository factory) class looks like later. I am also archtecting the application in a way that everything is implemented thru interfaces. I dont want the client code to be aware of how things are implemented but rather just how to use them. A real world example is a car for example, the manufacturer makes the car and to be able to drive it, we just need to know how to interact with its interfaces (streering wheel, brakes,etc..) we dont need to know how they work internally. So, all my client code need to be concerned about is how to use the interfaces i hand over to it. Now, looking at the PhysicianPipe class we can see that we can easily add some method that involve work across multiple repositories, then when we are done we can save the changes - we can have something like this:

   1:  public void DoWork(Domain.Entities.Physician physician)
   2:  {
   3:      repositoryGarden.PhysicianRepository.Add(physician);
   4:      repositoryGarden.ClinicRepository.DoSomework();
   5:      repositoryGarden.SaveRepositoryChanges();
   6:  }

Let's take a look at how I signed the repository garden class:

   1:  public class RepositoryGarden : IRepositoryGarden,IDisposable
   2:  {
   3:      IUnitOfWork _CurrentUoW;
   4:      public RepositoryGarden(IUnitOfWork unitOfWork)
   5:      {
   6:          if (unitOfWork == (IUnitOfWork)null)
   7:              throw new ArgumentNullException("unitOfWork", 
   8:                        "Can Not Be Null");
   9:                  _CurrentUoW = unitOfWork;
  10:      }
  11:      IPhysicianRepository physicianRepository = 
  12:                                        default(IPhysicianRepository);
  13:      IClinicRepository clinicRepository = default(IClinicRepository);
  14:   
  15:      public IPhysicianRepository PhysicianRepository
  16:      {
  17:          get
  18:          {
  19:              if (physicianRepository == null)
  20:              {
  21:                  physicianRepository = new PhysicianRepository(_CurrentUoW);
  22:              }
  23:              return physicianRepository;
  24:          }
  25:      }
  26:   
  27:      public IClinicRepository ClinicRepository
  28:      {
  29:          get
  30:          {
  31:              if (clinicRepository == null)
  32:              {
  33:                  clinicRepository = new ClinicRepository(_CurrentUoW);
  34:              }
  35:              return clinicRepository;
  36:          }
  37:      }
  38:   
  39:      //... More repositories
  40:   
  41:      public void SaveRepositoryChanges()
  42:      {
  43:          _CurrentUoW.Commit();
  44:      }
  45:   
  46:      public void Dispose()
  47:      {
  48:          if (_CurrentUoW != null)
  49:          {
  50:              _CurrentUoW.Dispose();
  51:          }
  52:          GC.SuppressFinalize(this);
  53:      }
  54:  }

And the signiture of IRepositoryGarden :

   1:  public interface IRepositoryGarden
   2:  {
   3:        IPhysicianRepository PhysicianRepository { get; }
   4:        IClinicRepository ClinicRepository { get; }
   5:        // More Repository interfaces.....
   6:        void SaveRepositoryChanges();
   7:  }

In this post I did not go over the details of each repository or the UnitOfWork, my goal was to show how easy we can create a central Repository Factory class that takes care of picking out desired repositories as needed then saving the changes once we're done. In my next post i will show how to use the Specification Pattern as well as using DataAnnotations to validate data in subsequent posts.

Friday, January 14, 2011

Forbidden Namespace Dependencies Wildcard

The architecture modeling project that shipped with Visual Studio 2010 has some nice features, one of which is the Layer Diagram where you can drop assemblies, namespaces, classes, and methods. There is one feature that is not supported yet and it's the ability to specify a wildcard in the Forbidden Namespace Dependencies as well as the Forbidden Namespace properties of a particular layer inside the layer diagram. The idea behind this is that i need to be able to write something like: MyRootNamespace.* and the tool I wrote would list out all namespaces under the root namespace, further i could write something like MyRootNamespace.Level1.* and get same results. So, I wrote some code to do that task for any layer diagram in a modeling project. Below is a screenshot of the properties window. Just click on a layer and hit F4 to get to it.


It's straight forward and uses LINQ to XML. So, let's see how it's done.
First, I created a method that get me some namespaces to work with.

   1:  protected static void GetWorkingNameSpaces(string AssembliesDir)
   2:  {
   3:      Namespaces = new HashSet<string>();
   4:      DirectoryInfo di = new DirectoryInfo(AssembliesDir);
   5:      var workingAssemblies = di.Exists ? 
   6:                                di.EnumerateFiles()
   7:                                  .Where(s=>s.Extension.ToLower() ==".dll" ||
   8:                                 s.Extension.ToLower() == ".exe" ) : null;
   9:      Parallel.ForEach(workingAssemblies, a =>
  10:      {
  11:          Assembly reference = Assembly.ReflectionOnlyLoadFrom(a.FullName);
  12:          try
  13:          {
  14:              HashSet<string> refernceNamespaces = 
  15:                  new HashSet<string>(reference.GetTypes()
  16:                                               .Select(f => f.Namespace)
  17:                                               .Where(n => n != null));
  18:              Namespaces.UnionWith(refernceNamespaces);
  19:          }
  20:          catch (ReflectionTypeLoadException) { }
  21:      });
  22:  }

So, not a whole lot going on, just newing up an instance of a HashSet and doing reflection over a list of assemblies and extracting some namespaces, and storing them in a HashSet collection so that i can work with them later.

Next, I created a method that will process the wildcard token. It takes in a namespace root or sub-n-root and returns nested namespaces.

   1:  protected static HashSet<string> ProcessWildCard(string Token)
   2:  {
   3:      HashSet<string> namespaces = new HashSet<string>();
   4:      int index = default(int);
   5:      string Name = default(string);
   6:      if (Token.Contains("."))
   7:          index = Token.LastIndexOf('.');
   8:      else return namespaces;
   9:      Name = Token.Substring(0, index).Trim();
  10:      foreach (var t in from c in Namespaces 
  11:                          where c.StartsWith(Name) 
  12:                          select c)
  13:      {
  14:          namespaces.Add(t);
  15:      }
  16:      return namespaces;
  17:  }

Now that i got this far, i need to build an update method that takes in an attribute Name and an XElement - since I am going to be updating both the Forbidden Namespace Dependencies and Forbidden Namespaces.

   1:  protected static void UpdateForiddenAttribute(ref string 
   2:                                                forbiddenAttributeName,
   3:                                                XElement t)
   4:  {
   5:      List<string> proccessed = new List<string>();
   6:      string _forbiddenAttributeValue = default(string);
   7:      if (t.Attribute(forbiddenAttributeName) != null)
   8:      {
   9:          _forbiddenAttributeValue = 
  10:                  t.Attribute(forbiddenAttributeName).Value;
  11:          string[] elements = default(string[]);
  12:          if (_forbiddenAttributeValue.Contains(";"))
  13:          {
  14:              elements = _forbiddenAttributeValue.Split(new[] { ";" },
  15:                               StringSplitOptions.RemoveEmptyEntries);
  16:          }
  17:          else
  18:          {
  19:              elements = new[] { _forbiddenAttributeValue };
  20:          }
  21:          foreach (var s in elements)
  22:          {
  23:              if (s.Contains("*") && !(s.Contains(",") || s.Contains("|")))
  24:              {
  25:                  var hash = ProcessWildCard(s);
  26:                  if (hash.Count > 0)
  27:                      foreach (var h in hash)
  28:                      {
  29:                          proccessed.Add(h);
  30:                      }
  31:                  else
  32:                  {
  33:                      proccessed.Add(s);
  34:                  }
  35:              }
  36:              else
  37:              {
  38:                  proccessed.Add(s);
  39:              }
  40:          }
  41:      }
  42:      string formattedAttributeValue = default(string);
  43:      if (proccessed.Count > 1)
  44:      {
  45:          formattedAttributeValue = String.Join(";", proccessed);
  46:      }
  47:      else
  48:      {
  49:          if (proccessed.Count == 1)
  50:              formattedAttributeValue = proccessed[0];
  51:          else
  52:              formattedAttributeValue = null;
  53:      }
  54:      t.SetAttributeValue(forbiddenAttributeName, formattedAttributeValue);
  55:  }

So far so good, all i did is get some attribute value, do some processing on it and update the .layerdiagram file with the newly constructed list of namespaces. So, the next step is the actual method that runs and collects data about the layerdiaram file/s in the modeling project, calls the update method and finally saves each layerdiagram file to complete the process.

   1:  static void RunTool(string layerdiagramDirectoryPath, 
   2:                      string AssembliesDirectory)
   3:  {
   4:      string forbiddenNamespaceDependenciesName = 
   5:                              "forbiddenNamespaceDependencies";
   6:      string forbiddenNamespaceName = "forbiddenNamespace";
   7:      GetWorkingNameSpaces(AssembliesDirectory);
   8:   
   9:      var q= Directory.EnumerateFiles(layerdiagramDirectoryPath, 
  10:                                      "*.layerdiagram", 
  11:                                      SearchOption.AllDirectories)  
  12:          .Select(x => new{
  13:                  s =  XDocument.Load(x),
  14:                  p = x 
  15:              })
  16:          .Where(d => d.s.Root
  17:                      .Elements()
  18:                      .Descendants()
  19:                      .Any(v => v.Attributes(
  20:                       forbiddenNamespaceDependenciesName)
  21:                      .Any())
  22:                  ||d.s.Root
  23:                      .Elements()
  24:                      .Descendants()
  25:                      .Any(v => v.Attributes(forbiddenNamespaceName)
  26:                      .Any())
  27:                  );
  28:      foreach (var x in q)
  29:      {
  30:          bool DocumentHasChanges = default(bool);
  31:          IEnumerable<XElement> xElements = 
  32:                  ( from c in x.s.Root
  33:                              .Elements()
  34:                              .Descendants()
  35:                  where c.Attributes(forbiddenNamespaceDependenciesName)
  36:                         .Any() ||
  37:                          c.Attributes(forbiddenNamespaceName).Any()
  38:                  select c
  39:                  );
  40:          Parallel.ForEach(xElements, t =>
  41:          {
  42:              if (t.Attribute(forbiddenNamespaceDependenciesName) != null)
  43:              {
  44:                  UpdateForiddenAttribute(ref 
  45:                                   forbiddenNamespaceDependenciesName, t);
  46:                  DocumentHasChanges = true;
  47:              }
  48:              if (t.Attribute(forbiddenNamespaceName) != null)
  49:              {
  50:                  UpdateForiddenAttribute(ref forbiddenNamespaceName, t);
  51:                  DocumentHasChanges = true;
  52:              }
  53:          });
  54:          if (DocumentHasChanges)
  55:          x.s.Save(x.p);
  56:      }
  57:  }

And that's all the code needed to now have an out of box wildcard functionality. To get this working just hook it up to the main entry point of your program and pass in 2 arguments (modeling project directory and assemblies directory) and wrap it up with a try catch block. Would look something like this:

   1:  #region Program Entry
   2:      public static void Main(string[] args)
   3:      {
   4:          try
   5:          {
   6:              RunTool(args[0], args[1]);
   7:          }
   8:          catch (Exception g)
   9:          {
  10:              Console.WriteLine("Error :{0} ", g.Message);
  11:          }
  12:      }
  13:  #endregion

So, to use this tool, right click on the modeling project and choose Edit project - add an MSBUILD Exec task and give it the location of batch file under your solution items or where ever you like to keep .bat files related to your solution and that's all. Next time you build the solution and if there are any broken forbidden namespace dependencies, they will show up as build errors.