Search code examples
c#ooplazy-loading

Circular dependency when Lazy Loading between BL and BE


I have basically a business layer, a business entities and a data access (SQL) layer.

The business entities layer is referenced by business layer and data access layer.

I've made a test to set lazyloading in which one I call function that fills entities from business layer to entity layer.

Issue: circular dependency! I can not call BL from BE because BE is used by BL

Here is the code that is interesting:

Entity properties:

 // Not lazyloaded properties
        public int Id { get; set; }
        public string Description { get; set; }

        // lazy loaded properties
        private Lazy<AuditTypeEntity> _auditType = null;
        public AuditTypeEntity auditType
        {
            get
            {
                return _auditType.Value;
            }
        }

Entity constructor that I've made (but I can't use it because there is a circular redundancy: BL calls BE so BE can't call BL):

public MyEntity()
        {
        _auditType = new Lazy<AuditTypeEntity>(() => BusinessLayer.GetAuditTypeById(_auditTypeId).Value);
}
        

EDIT:

I'm using ADO.NET and it fills an entity object.

Here is an example on how I call my DAL layer:

public static IList<Nature> GetAllNature()
        {
            using (DAOManager daomanager = DAOFactory.CreateDaoManager(DataSource.DB_Belval))
            {
                return daomanager.GetNatureDAO().GetAll(BE.EnumEntity.NATURE.ANOMALY);
            }
        }

Solution

  • Here is an example on how you can achieve this. As that, you can use a custom constructor in order to give Lazy dependencies.

    ! The DAL is the only one that should handle Lazy !

    class Program
    {
        static void Main(string[] args)
        {
            var bll = new BLL();
            var person = bll.GetPerson();
            var orders = person.Orders; // GetOrders in DAL will be excuted here
        }
    }
    
    // BLL project
    public class BLL
    {
        public Person GetPerson()
        {
            return new DAL().GetPerson(1);
        }
    }
    
    // Entity Project
    public class Person
    {
        public Person()
        {
    
        }
        public Person(Lazy<IEnumerable<Order>> orders)
        {
            _orders = orders;
        }
        public int Id { get; set; }
        public string Name { get; set; }
        private Lazy<IEnumerable<Order>> _orders = null;
    
        public IEnumerable<Order> Orders
        {
            get { return _orders?.Value; }
            set { _orders = new Lazy<IEnumerable<Order>>(() => value); }
        }
    
    }
    
    public class Order
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    // DAL Project
    public class DAL
    {
        public Person GetPerson(int id)
        {
            var person = new Person(new Lazy<IEnumerable<Order>>(() => GetOrders(id))) // Init lazy
            {
                Id = id,
                Name = "Person"
            };
            return person;
        }
    
        public IEnumerable<Order> GetOrders(int personId)
        {
            return new List<Order> { new Order { Id = 2, Name = "Order" } };
        }
    }