Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository vs Data Access

In the context of the n-tier application, is there a difference between what you would consider your data access classes to be and your repositories?

I tend to think yes but I just wanted to see what other thought. My thinking is that the job of the repository is just to contain and execute the raw query itself, where as the data access class would create the context, execute the repository (passing in the context), handle mapping the data model to the domain model and return the result back up...

What do you guys think? Also do you see any of this changing in a Linq to XML scenario (assuming that you change the context for the relevant XDocument)?

Cheers Anthony

UPDATE:

This is the way that I would have typically implemented things previously:

public class TermBl : ITermBl
{
    public IEnumerable<ITerm> GetAll(IListParameter criteria)
    {
        //Any pre business logic

        var dataLayer = this.CreateDataLayer();
        var result = dataLayer.GetAll(criteria);

        //Any post business logic

        return result;
    }

    ... Other methods
}

public class TermDa : ITermDa
{
    public IEnumerable<ITerm> GetAll(IListParameter criteria)
    {
        //Linq query
        var dataResult = ....ToList()

        var mappedResult = this.FromDataToDomain(dataResult);   
        //Note the mapping isn't done in this object, the actual 
        //  mapping is handled by a separate component

        return mappedResult;
    }

    ... Other methods
}

Do you see any inherent problems here with the pattern in general...

As for the repository where I have been thinking of using the it is instead of having the query directly in the TermDa's GetAll method I would change it to look something more like this:

public class TermDa : ITermDa
{
    public IEnumerable<ITerm> GetAll(IListParameter criteria)
    {
        var repository = this.CreateRepository();
        var dataResult = repository.GetAll(..., criteria).ToList();

        var mappedResult = this.FromDataToDomain(dataResult);

        return mappedResult;
    }

    ... Other methods
}

public class TermRepository : ITermRepository 
{
    public IQueryable<ITerm> GetAll(IMyContext context, IListParameter criteria)
    {
        //Linq query
        return  ...;
    }

    ... Other queries
}

Is this how you guys see it working or not really... With or without the repository I see either of the above totally protecting the business layer from knowing anything about the data access methods/technology used...

like image 386
vdh_ant Avatar asked May 06 '10 13:05

vdh_ant


2 Answers

Yes, there is a major difference.

  • A DAL (such as a Table Data Gateway) is a database concept. It is responsible for issuing queries to the database and returning record sets.

  • A repository is a domain concept. It is responsible for accepting structured requests and returning strongly-typed objects.

Very different in practice.


Update:

The question seems to reflect a significant amount of confusion, so let me try to clarify with a code example. Here's a design you might use if you weren't using any ORM and were doing all of your own mapping instead. None of this is production-quality code, it's just for educational purposes:

Data Access:

public interface IOrderData
{
    IDataReader GetOrder(int orderID);
}

public interface IOrderDetailData
{
    IDataReader GetOrderDetails(int orderID);
}

public interface IProductData
{
    IDataReader GetProduct(int productID);
}

Domain:

public class Order
{
    public int ID { get; set; }
    public DateTime Date { get; set; }
    public OrderStatus Status { get; set; }
    // etc.
    public IList<OrderDetail> Details { get; set; }
}

public class OrderDetail
{
    public int ID { get; set; }
    public Product Product { get; set; }
    public int Quantity { get; set; }
}

Mapping:

public interface IDataMapper
{
    Order MapOrder(IDataRecord record);
    OrderDetail MapOrderDetail(IDataRecord record);
    Product MapProduct(IDataRecord record);
}

Repository:

public interface IOrderRepository
{
    Order GetOrder(int orderID);
}

public class OrderRepository
{
    // These get initialized in the constructor
    private readonly IOrderData orderData;
    private readonly IOrderDetailData orderDetailData;
    private readonly IProductData productData;
    private readonly IDataMapper mapper;

    public Order GetOrder(int orderID)
    {
        Order order;
        using (IDataReader orderReader = orderData.GetOrder(orderID))
        {
            if (!orderReader.Read())
                return null;
            order = mapper.MapOrder(orderReader);
        }
        using (IDataReader detailReader = 
            orderDetailData.GetOrderDetails(orderID))
        {
            while (detailReader.Read())
            {
                OrderDetail detail = mapper.MapOrderDetail(detailReader);
                detail.Product = ...;  // Omitted for brevity, more reading/mapping
                order.Details.Add(detail);
            }
        }
        return order;
    }
}

Is this making more sense now? The DAL is dealing with data. The concrete Repository may encapsulate data access classes but the abstract repository (its public interface) only deals with domain classes.

Once again I'll just remind readers that this is not even close to production-quality code, and that most apps today use an ORM or at least some better form of automatic mapping. This is for illustrative purposes only.

like image 111
Aaronaught Avatar answered Oct 23 '22 14:10

Aaronaught


You seem to have a good handle on it. "Data Access classes" can take a lot of different shapes. It's some sort of class that has something to do with data access. Your Repository is (A) a pattern for handling your data persistence, and (B) a place within your data access scheme (if you're implementing repository).

A challenge in your data access strategy is providing flexibility and reusable capability at the same time. While at the same time being efficient. While at the same time working with your business logic, being decoupled but also being cohesive. Tricky.

Repository is a pattern that purports to help with all this balance. Your code for translating the db (or whatever) to/from entity classes resides in one place, for each entity. Your "Data Access classes" might consist of your repository classes, as well as classes that actually handle sql work. You certainly should not be doing all the sql cruft within each of your repository classes.

Example: you could start off using inefficient-but-easy reflection to fill out your entity objects, doing close to no work in your repository classes; later you can make it more efficient for high-volume entities, but this is completely hidden from other parts of your system. And then later you move some configuration to XML, but the rest of your system has no idea of this change.

LINQ-to-sql and Entity framework really leverage the repository pattern, because what the repository classes return is actually an IQuerable of that entity. Business classes can apply additional criteria, and those criteria actually make it to the sql, while still providing complete encapsulation from the data persistence. It's seriously cool.

like image 34
Patrick Karcher Avatar answered Oct 23 '22 16:10

Patrick Karcher