views:

1007

answers:

3

If you have, for example, a database table called Person (ID,Name etc) what kind of object should the data access tier return to the business tier? I'm thinking something like this:

//data access tier
public class DataAccess{

   public interface IPerson{
      int ID{ get; set; }
      string Name{ get; set; }
   }

   internal class Person : IPerson{
      private int id;
      private string name;

      public int ID{ get{return id; } set{ id=value; } }
      public int Name{ get{retutn name; } set{ name=value; }
   }

   public static IPerson GetPerson(int personId)
   {
      //get person record from db, populate Person object
      return person;  
   }
}

//business tier
public class Person : IPerson{
   private int id;
   private string name;

   public int ID{ get{return id;} set{id=value;} }
   public string Name{ get{return name;} set{name=value;} }

   public void Populate(int personId){
      IPerson temp = DataAccess.GetPerson(personId);
      this.ID = temp.ID;
      this.Name = temp.Name;
   }
}

But this all seems a little cumbersome? Is there a more elegant solution to this problem? Should I return a DataRow from the data access layer to the business layer instead?

+14  A: 

You don't need to repeat the class definition in your data access layer (DAL).

You can create your business entities as 'dumb' containers in a separate assembly, e.g. your Person class can just be:-

public class Person
{
    int ID { get; set: }
    string Name { get; set: }
}

Then, you can give your DAL a reference to the business entities layer. Your controller objects, whether they are in a separate business logic layer, or within your UI layer, can then just call the DAL, which can create a business entity, populate it from the database and return it to your controller.

This article by Imar Spaanjaars has a nice explanation of this pattern.

AdamRalph
Wouldn't giving the DAL a reference to the business entities layer create a [undesirable] two-way dependency?
mdresser
No, the business entities layer will have no refence to the DAL. It's just an assmebly of 'dumb' container objects. The part of your app (UI or seperate business logic layer) which is requesting them from the DAL should be in another part of the assembly and should reference both DAL and entities.
AdamRalph
Assembly A: Class definition, nothing but fields and properties. Domain assembly.Assembly B: DAL. References assembly A.Assembly C: UI. References assembly A and B.
yodaj007
@Rich Seller - thanks for the spelling correction
AdamRalph
@yodaj007 - correct. You can also introduce a business logic layer (BLL) like the 'Manager' classes in Imar's articles. Your 'domain assembly' equates to Imar's business objects assembly (BO). The references are then:- UI->BO, UI->BLL, BLL->BO, BLL->DAL, DAL->BO.
AdamRalph
+3  A: 

Your business layer definitely doesn't want to know about data rows - try to leave data specific classes in the data layer. This reduces coupling and frees you to change your persistence layer at a later date without wholesale re-architecting.

To solve your specific problem, you can either:

  • Create basic data objects/entities in your data layer and hand them off to your business layer for consumption.
  • Or, as it seems you are doing, create DTOs (Data Transfer Objects) that exist purely as a means of transferring data from the data layer to a richer implementation of your business object in a higher layer. You might do this as part of a repository pattern in a rich domain model.

The other thing you might want to think about is tiers v layers - it makes a difference how you think about these things. Tiers are generally physical, in other words they define the boundaries between processes. Layers are generally logical, they separate a program's functionality into loosely coupled units. You are aiming for layers in this case.

flesh
+1  A: 

If you create interfaces to your DAO classes and place them within your business tier, you can reference your business tier from the Data Access tier. The DAO classes in the data tier return objects from the business tier.

Your business tier references the interfaces instead of directly referencing the data access objects. Dependency injection via an IoC container (like Castle Windsor for example) will allow you to accomplish this.

This technique is called separated interfaced and is described here:

http://www.martinfowler.com/eaaCatalog/separatedInterface.html

The best explanation of this technique I have seen can be found in this article on NHibernate best practices, written by Billy McCafferty.

http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx

The article has alot of information that is specific to NHiberbate, but a good half of it is just solid information on designing applications to be loosely coupled and easily unit tested.

Jim Petkus