Posts Tagged ‘design patterns’

Data Access Architecture

While I’ve been reading about software architecture, design patterns and stuff like that, I’ve found Udi Dahan – The Software Simplist page as a valuable resource for learning.

Began reading about Data Access layers, options, ORM’s, Domain Models.

Check these references:

Pragmatic Architecture: Data Access
nhibernate posts by Udi Dahan
datasets posts by Udi Dahan
business-rules posts by Udi Dahan
Object Relational Mapping Sucks!
Dataset – O/R mapping rumble at TechEd MVP Dinner
Domain Model Pattern
First time here – Using Domain Models
AnemicDomainModel

Implementing the Repository Pattern in C# ASP .NET

Excellent post by Kori Becker: Implementing the Repository Pattern in C# ASP .NET

Source code: here or here

I mean, I got to understand this Repository Patter stuf thanks to this excellent yet simple example.

A class:

public class Planet
{
    public int PlanetId;
    public string Name;
    public bool IsTerraform;

    public Planet()
    {
    }

    public Planet(int planetId, string name, bool isTerraform)
    {
    PlanetId = planetId;
    Name = name;
    IsTerraform = isTerraform;
}
}

An interface:

public interface IPlanetRepository
{
    List<Planet> GetPlanets();
    List<Planet> GetStars();
}

A MS SQL Server repository:

public class MSSQLPlanetRepository : IPlanetRepository
{
    #region IPlanetRepository Members

    public List<Planet> GetPlanets()
    {
    // Simulate returning the list of data from the database.
    List<Planet> planetList = new List<Planet>();

    // SqlConnection code would actually go here, this is to keep things simple.
    planetList.Add(new Planet(1, "Mercury", false));
    planetList.Add(new Planet(2, "Venus", true));
    planetList.Add(new Planet(3, "Earth", true));
    planetList.Add(new Planet(4, "Mars", true));
    planetList.Add(new Planet(5, "Jupiter", false));
    planetList.Add(new Planet(6, "Saturn", false));
    planetList.Add(new Planet(7, "Uranus", false));
    planetList.Add(new Planet(8, "Neptune", false));
    planetList.Add(new Planet(9, "Pluto", false));

    return planetList;
    }

    public List<Planet> GetStars()
    {
    // Simulate returning the list of data from the database.
    List<Planet> planetList = new List<Planet>();

    // SqlConnection code would actually go here, this is to keep things simple.
    planetList.Add(new Planet(1, "Sun", false));

    return planetList;
    }

    #endregion
}

A BussinessLayer:

public class PlanetBusiness
{
    IPlanetRepository _repository;

    public PlanetBusiness(IPlanetRepository repository)
    {
      _repository = repository;
    }

    public List<Planet> GetPlanets()
    {
      return _repository.GetPlanets();
    }

    public List<Planet> GetStars()
    {
      return _repository.GetStars();
    }

    public List<Planet> GetTerraformPlanets()
    {
      // Return the list of filtered data from the database.
      List<Planet> planetList = _repository.GetPlanets();

      var results = from p in planetList
      where p.IsTerraform == true
      select p;

      return results.ToList();
    }
}

Presentation layer:

static void Main(string[] args)
{
    // Load planets from the MSSQL repository.
    PlanetBusiness planetBusiness = new PlanetBusiness(new MSSQLPlanetRepository());

    List<Planet> planetList = planetBusiness.GetPlanets();
    foreach (Planet planet in planetList)
    {
      Console.WriteLine(planet.PlanetId + ". " + planet.Name);
    }
}

An Oracle repository:

public class OracleRepository : IPlanetRepository
{
    #region IPlanetRepository Members

    public List<Planet> GetPlanets()
    {
      // Simulate returning the list of data from the database.
      List<Planet> planetList = new List<Planet>();

      // OracleConnection code would actually go here, this is to keep things simple.
      planetList.Add(new Planet(1, "Mercury", false));
      planetList.Add(new Planet(2, "Venus", true));
      planetList.Add(new Planet(3, "Earth", true));
      planetList.Add(new Planet(4, "Mars", true));
      planetList.Add(new Planet(5, "Jupiter", false));
      planetList.Add(new Planet(6, "Saturn", false));
      planetList.Add(new Planet(7, "Uranus", false));
      planetList.Add(new Planet(8, "Neptune", false));
      planetList.Add(new Planet(9, "Pluto", false));
      planetList.Add(new Planet(10, "Planet X", false));

      return planetList;
    }

    public List<Planet> GetStars()
    {
      // Simulate returning the list of data from the database.
      List<Planet> planetList = new List<Planet>();

      // OracleConnection code would actually go here, this is to keep things simple.
      planetList.Add(new Planet(1, "Sun", false));
      planetList.Add(new Planet(2, "Alpha Centauri", false));

      return planetList;
  }

  #endregion
}

Just change to this in Presentation Layer:

static void Main(string[] args)
{
    // Load planets from the Oracle repository.
    PlanetBusiness planetBusiness = new PlanetBusiness(new OraclePlanetRepository());

    List<Planet> planetList = planetBusiness.GetPlanets();
    foreach (Planet planet in planetList)
    {
      Console.WriteLine(planet.PlanetId + ". " + planet.Name);
    }
}

A Unit Testing repository:

public class TestRepository : IPlanetRepository
{
    #region IPlanetRepository Members

    public List<Planet> GetPlanets()
    {
      // Simulate returning the list of data from the database.
      List<Planet> planetList = new List<Planet>();

      planetList.Add(new Planet(1, "Earth", true));
      planetList.Add(new Planet(2, "Test Planet", true));

      return planetList;
    }

    public List<Planet> GetStars()
    {
      // Simulate returning the list of data from the database.
      List<Planet> planetList = new List<Planet>();

      planetList.Add(new Planet(1, "None", false));

      return planetList;
    }

    #endregion
}

Accessing all repositories at once from Presentation Layer:

static void Main(string[] args)
{
    // Load planets from the MSSQL repository.
    PlanetBusiness planetBusiness = new PlanetBusiness(new MSSQLPlanetRepository());
    TestPlanets(planetBusiness);

    // Load planets from the Oracle repository.
    planetBusiness = new PlanetBusiness(new OracleRepository());
    TestPlanets(planetBusiness);

    // Load planets from the Test repository.
    planetBusiness = new PlanetBusiness(new TestRepository());
    TestPlanets(planetBusiness);

    Console.ReadKey();
}

private static void TestPlanets(PlanetBusiness planetBusiness)
{
    // Basic driver class to test our planet business class and display output.
    Console.WriteLine();
    Console.WriteLine("Planets:");
    Console.WriteLine();

    List<Planet> planetList = planetBusiness.GetPlanets();
    foreach (Planet planet in planetList)
    {
      Console.WriteLine(planet.PlanetId + ". " + planet.Name);
    }

    Console.WriteLine();
    Console.WriteLine("Terraformable Planets:");
    Console.WriteLine();

    planetList = planetBusiness.GetTerraformPlanets();
    foreach (Planet planet in planetList)
    {
      Console.WriteLine(planet.PlanetId + ". " + planet.Name);
    }
}

Using C# .NET reflection to automatically implement the desired concrete repository at run-time, by reading the web.config:

    <appSettings>
    <!-- The assembly name of the default repository. Use the format Fully.Qualified.Class.Name, Assembly.FileName -->
    <add key="DefaultRepository" value="RepositoryPatternTest.Repository.Repositories.MSSQLPlanetRepository, RepositoryPatternTest.Repository" />
    </appSettings>

On Presentation Layer:

static void Main(string[] args)
{
    // Load planets from the default repository as specified in the web.config. Allows for changing the repository at run-time, without changing code!
    Type obj = Type.GetType(ConfigurationManager.AppSettings["DefaultRepository"]);
    ConstructorInfo constructor = obj.GetConstructor(new Type[] { });
    IPlanetRepository defaultRepository = (IPlanetRepository)constructor.Invoke(null);

    PlanetBusiness planetBusiness = new PlanetBusiness(defaultRepository);
    TestPlanets(planetBusiness);

    Console.ReadKey();
}

 

References:

 

Repository by Martin Fowler

ASP.NET MVC using the Repository Pattern on StackOverflow.com

Using the Entity Framework Repository and UnitOfWork Pattern in C# ASP .NET

Using Repository and Unit of Work patterns with Entity Framework 4.0

 

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 78 seguidores