Code Guru
Code Guru

Reputation: 143

Lazy loading child list within a BusinessObject

I am using a 3-layer (UI, BLL, DAL) architecture and use BusinessObjects (aka Data Transfer Objects - DTO) between these layers. Suppose I have the following DTOs:

public class EmployeeDTO
{
    public int EmpID { get; set; }
    public string Name { get; set; }
    public ICollection<EmailDTO> EmailList { get; set; }
}

public class EmailDTO
{
    public int EmailID { get; set; }
    public string Message { get; set; }
}

I want to lazyload the EmailList collection when I use the EmployeeDTO since it can be alot of data. So basically the EmployeeDTO will be created at the DAL level (without Email collection) and sent back to the UI via BLL. At this point how can I lazyload the EmailList at the UI Level. My code (omitting details) is similar to the following:

UI

{
    EmployeeDTO empDTO = new EmployeeBLL().GetEmployeeByID (id);
}

BLL

public EmployeeDTO GetEmployeeByID (id)
{
    return new EmployeeDAL().GetEmployeeByID (id);
}

DAL

public EmployeeDTO GetEmployeeByID (id)
{
    reader = get employee data by id...

    EmployeeDTO empDTO = new EmployeeDTO ();
    empDTO.EmpID = reader [1];
    empDTO.Name  = reader [2];
    // I can load the email list but i dont
    return empDTO;
}

Now at the DAL level when I use empDTO.EmailList (), it should lazy load the data. How can i do so. I need a clean solution (please note I am not using any ORM). Thanks.

Upvotes: 0

Views: 197

Answers (1)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236268

First - declare emails as virtual:

public class EmployeeDTO
{
    public int EmpID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<EmailDTO> EmailList { get; set; }
}

Next - create class, which inherits from EmployeeDTO and provides lazy-loading functionality:

public class LazyEmployeeDTO : EmployeeDTO
{
    public override ICollection<EmailDTO> EmailList
    {
        get 
        {
            if (base.EmailList == null)
               base.EmailList = LoadEmails();

            return base.EmailList;
        }

        set { base.EmailList = value; }
    }

    private ICollection<EmailDTO> LoadEmails()
    {
        var emails = new List<EmailDTO>();
        // get emails by EmpID from database
        return emails;            
    }
}

And last - return LazyEmployeeDTO from DAL, but make sure that client depend on simple EmployeeDTO:

public EmployeeDTO GetEmployeeByID (id)
{
    reader = get employee data by id...

    EmployeeDTO empDTO = new LazyEmployeeDTO();
    empDTO.EmpID = reader[1];
    empDTO.Name  = reader[2];
    // do not load emails
    return empDTO;
}

Rest of code should stay as is. This lazy employee will act as proxy for base employee, and clients will not know that they are not using EmployeeDTO.

Upvotes: 2

Related Questions