Showing posts with label Repository Pattern. Show all posts
Showing posts with label Repository Pattern. Show all posts

Wednesday, August 21, 2013

Generate Repository Pattern for Entity Framework DbContext

Generating Repositories for the database entities could be a big repetitive task with similar code. The project at https://efrepository.codeplex.com solves the problem by generating a T4 Template for the edmx model. The T4 Template then generates the required repositories, the Unit of Work pattern, and also provides a factory for the repositories.

The template, however, generates code for the ObjectContext approach.

I have modified the template, so that it can be used with the EntityFramework 5.0 and above to generate the relevant repositories.

Here is the Template below.


//==========================================================================
<#@ template language="C#" debug="true" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
 
<#@ output extension=".cs"#>
<#
 
// This needs to be set to the .edmx file that you want to process.
string edmxFile = FindEDMXFileName(); // @"Model1.edmx";
 
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
MetadataTools ef = new MetadataTools(this);
 
#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace <#= code.VsNamespaceSuggestion() #>
{ 
 public interface IRepository 
 {
  IUnitOfWork UnitOfWork { get; set; }
  IQueryable All();
  IQueryable Where(Func expression);
  void Add(T entity);
  void Delete(T entity);
 }
}<#
 
 
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(edmxFile);
EntityContainer container = ItemCollection.GetItems().FirstOrDefault();
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
 
foreach (EntityType entity in ItemCollection.GetItems().OrderBy(e => e.Name))
{;
 
 if(!DoesFileExist(entity.Name + "Repository.cs"))
 {
  fileManager.StartNewFile(entity.Name + "Repository.cs");
  #>using System;
using System.Linq;
using System.Collections.Generic;
 
namespace <#= code.VsNamespaceSuggestion() #>
{   
 <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#>Repository : EFRepository<<#=code.Escape(entity)#>>, I<#=code.Escape(entity)#>Repository
 {
 
 }
 
 <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#> interface I<#=code.Escape(entity)#>Repository
 {
 
 }
}<#
 }
 else
 {
  fileManager.StartNewFile(entity.Name + "Repository.cs");
  this.Write(OutputFile(entity.Name + "Repository.cs"));
 }
}
 
fileManager.StartNewFile("IUnitOfWork.cs");
#>using System.Data.Objects;
using System.Data.Entity;
 
namespace <#= code.VsNamespaceSuggestion() #>
{
 public interface IUnitOfWork
 {
  DbContext Context { get; set; }
  void Commit();
  bool LazyLoadingEnabled { get; set; }
  bool ProxyCreationEnabled { get; set; }
  string ConnectionString { get; set; }
 }
}<# fileManager.StartNewFile("RepositoryIQueryableExtensions.cs");
#>using System.Data.Objects;
using System.Linq;
 
namespace <#= code.VsNamespaceSuggestion() #>
{
 public static class RepositoryIQueryableExtensions
 {
  public static IQueryable Include
   (this IQueryable source, string path)
  {
   var objectQuery = source as ObjectQuery;
   if (objectQuery != null)
   {
    return objectQuery.Include(path);
   }
   return source;
  }
 }
}<# fileManager.StartNewFile("EFRepository.cs");
#>using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
 
namespace <#= code.VsNamespaceSuggestion() #>
{
 public class EFRepository : IRepository where T : class
 {
  public IUnitOfWork UnitOfWork { get; set; }
  
  private DbSet _dbSet;
 
  private DbSet DbSet
  {
   get
   {
    if (_dbSet == null)
    {
     _dbSet = UnitOfWork.Context.Set();
    }
    return _dbSet;
   }
  }
 
  public virtual IQueryable All()
  {
   return DbSet.AsQueryable();
  }
 
  public IQueryable Where(Func expression)
  {
   return DbSet.Where(expression).AsQueryable();
  }
 
  public void Add(T entity)
  {
   DbSet.Add(entity);
  }
 
  public void Delete(T entity)
  {
   DbSet.Remove(entity);
  }
 
 }
}<#fileManager.StartNewFile("EFUnitOfWork.cs");
#>using System.Data.Objects;
using System.Data.Entity;
 
namespace <#= code.VsNamespaceSuggestion() #>
{
 public class EFUnitOfWork : IUnitOfWork
 {
  public DbContext Context { get; set; }
 
  public EFUnitOfWork()
  {
   Context = new <#=code.Escape(container)#>();
  }
 
  public void Commit()
  {
   Context.SaveChanges();
  }
  
  public bool LazyLoadingEnabled
  {
   get { return true; }
   set { }
  }
 
  public bool ProxyCreationEnabled
  {
   get { return true; }
   set { }
  }
  
  public string ConnectionString
  {
   get { return Context.Database.Connection.ConnectionString; }
   set { Context.Database.Connection.ConnectionString = value; }
  }
 }
}
<#fileManager.StartNewFile("RepositoryHelper.cs");
#>
namespace <#= code.VsNamespaceSuggestion() #>
{
 public static class RepositoryHelper
 {
  public static IUnitOfWork GetUnitOfWork()
  {
   return new EFUnitOfWork();
  }  
  <# foreach (EntityType entity in ItemCollection.GetItems().OrderBy(e => e.Name))
{; #>
 
  public static <#=code.Escape(entity)#>Repository Get<#=code.Escape(entity)#>Repository()
  {
   return new <#=code.Escape(entity)#>Repository();
  }
 
  public static <#=code.Escape(entity)#>Repository Get<#=code.Escape(entity)#>Repository(IUnitOfWork unitOfWork)
  {
   var repository = new <#=code.Escape(entity)#>Repository();
   repository.UnitOfWork = unitOfWork;
   return repository;
  }  
<# } #>
 }
}<# fileManager.Process();
#>
 
 
<#+
 
bool DoesFileExist(string filename)
{   
 return File.Exists(Path.Combine(GetCurrentDirectory(),filename)); 
}
 
string OutputFile(string filename)
{
 using(StreamReader sr = new StreamReader(Path.Combine(GetCurrentDirectory(),filename)))
 {
  string contents = sr.ReadToEnd();
  return contents;
 }
}
 
string GetCurrentDirectory()
{
 string executingDirectoryName = "";
 string stackTraceFileName = new StackTrace(true).GetFrame(0).GetFileName();
 if (String.IsNullOrEmpty(stackTraceFileName))
 {
  throw new ArgumentException("No value was specified for the 'directoryName' configuration parameter" +
   ", and we could not figure out the file name from the stack trace (most likely because of running " +
   "the template with debug='False' specified in the <\u0023@ template \u0023> directive.");
 }
 else
 {  
  executingDirectoryName = Path.GetDirectoryName(stackTraceFileName);
 } 
 return executingDirectoryName;
}
 
string FindEDMXFileName()
{
 string edmxFile = "";
    
 string[] entityFrameworkFiles = Directory.GetFiles(GetCurrentDirectory(), "*.edmx");
 if(entityFrameworkFiles.Length > 0)
  edmxFile = entityFrameworkFiles[0];
 
 return edmxFile;
}
#>