Data Access Layer - Designing Class where should responsibility of creating saving be

1.5k views Asked by At

I am designing Data Access Layer with ADO.NET 2.0 and C#, Sql Server 2005. I often fight with my brain over where to place those calls. Which way of the below i should follow for maintainable robust code.

Method 1

Public Class Company
{

public string CompanyId
{get;set;}

public string CompanyAddress
{get;set;}

public bool Create()
{
}

public bool Update()
{
}

public bool Delete()
{
}

}

Method 2

Public Class Company
{

public string CompanyId
{get;set;}

public string CompanyAddress
{get;set;}
}

and i would use another class like below to do the core data access. Like below

Public Class CompanyRepository
{

public Company CreateCompany(string companyId,string companyDescription)
{
}

public bool UpdateCompany(Company updateCompany)
{
}

public bool DeleteCompany(string companyId)
{
}

public List<Company> FindById(string id)
{
}


}
3

There are 3 answers

13
Jason Down On BEST ANSWER

Go with method 2. It is not the Company class's responsibility to read/write from a data source (single responsibility principle). However, I would even go as far as creating an ICompanyRepository interface and then creating a CompanyRepository implementation for the interface. This way you can inject the ICompanyRepository into the class that needs to save/retrieve company information. It also allows easier unit testing and the ability to create a different implementation in the future (switching from a database to xml files or whatever).

3
Oded On

If you follow the principle of separation of concerns, you will go with your method 2.

Having different responsibilities in different classes does help with creating testable, maintainable code.

This also produces smaller, more cohesive classes that are easier to write, reason about and check for correctness.

As a note, you can use an ORM instead of hand crafting your data access layer.

0
Tigran On

I would stand for second choice, cause

  • first you create your data holder
  • after crate your operational unit

So in this case you separate the data from functions that operate on them, making UnitTesting notably easier and destributing the responsibilities between different domains of your code, with, possibly, easy bugs localizations.