在Business Objects中加载延迟子列表

时间:2013-07-29 16:31:00

标签: architecture lazy-loading n-tier-architecture

我正在使用3层(UI,BLL,DAL)架构,并在这些层之间使用BusinessObjects(也称为数据传输对象 - DTO)。假设我有以下DTO:

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; }
}

我想在使用EmployeeDTO时懒惰加载EmailList集合,因为它可能有很多数据。所以基本上EmployeeDTO将在DAL级别创建(没有Email集合),并通过BLL发送回UI。在这一点上,我如何在UI级别延迟加载EmailList。我的代码(省略细节)类似于以下内容:

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;
}

现在在DAL级别,当我使用 empDTO.EmailList()时,它应该延迟加载数据。我怎么能这样做。我需要一个干净的解决方案(请注意我没有使用任何ORM)。感谢。

1 个答案:

答案 0 :(得分:2)

首先 - 将电子邮件声明为虚拟:

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

下一步 - 创建类,它继承自EmployeeDTO并提供延迟加载功能:

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;            
    }
}

最后 - 从DAL返回LazyEmployeeDTO,但要确保客户端依赖于简单的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;
}

其余代码应保持原样。这个懒惰的员工将充当基础员工的代理,客户不会知道他们没有使用EmployeeDTO