Search code examples
c#asp.netentity-frameworkasp.net-identityasp.net-core-2.0

.Net Core 2.0 Web Api circular dependency after moving database context to DAL class library


I am making a Web Api that makes use of the Microsoft Identity service. To create a more maintainable project I decided to create a DAL(Data Acces Layer) project that is a simple class library, to make my code more compartmentalized.

I moved my dbcontext that inherits from IdentityDbContext to the DAL project. My BLL(Buissness Logic Layer) has a reference to my DAL so it can call the functions in my DAL, but because my dbcontext inherits from IdentityDbContext I need a reference in my BLL to my DAL so I can add the dbcontext service in my startup class, which ofcourse creates a circular dependency.

so my questions are

  1. Is it seen as a good practice to move your database context to your DAL?
  2. If so, how could I solve my problem so I dont need a reference from my DAL to my BLL?

Many thanks in advance.


Solution

  • Your data context belongs in the data access layer, should you follow the approach. However, depending on how you implement via the clean architecture (fancy terminology for onion architecture) or N-Tier architecture. The two approaches are designed to create a separation of concerns, however clean architecture often is even more abstracted and loosely coupled than a typical N-Tier architecture.

    The foundational approach though for your dependencies N-Tier would be along the following:

    Data Access Layer:

    • Domain Layer (Plain Old C# Objects)

    Service Layer (Optional):

    • Data Access Layer
    • Domain Layer

    Presentation Layer:

    • Service Layer

    However, if your incorporating in a framework such as Asp.Net Core you'll notice that your solution relies on middleware. The presentation layer for a module, controller, view all reside in the solution file. So you inadvertently would have a presentation layer to handle your UX, but will require your IServiceCollection to register those other dependencies creating a layer in line with:

    Presentation Layer:

    • Data Access Layer
    • Domain Layer
    • Service Layer

    This will resolve the circular dependency issue, but then you have to decide on your coupling approach. But this is the most common and barebones example you'll often see.

    Data Access Layer:

    public interface ISampleRepository : IDisposable
    {
         IEnumerable<SampleModel> GetAllSamples();
    }
    
    public class SampleContext : ISampleRepository
    {
         public IEnumerable<SampleModel> GetAllSamples()
         {
              // Implementation
         }
    }
    
    public interface ISampleFactory
    {
         ISampleRepository Create();
    }
    
    public class SampleFactory
    {
         ISampleRepository Create() => new SampleContext();
    }
    

    Service Layer:

    public class SampleService
    {
         IEnumerable<SampleModel> RetrieveSamples()
         {
              using(var context = new SampleFactory().Create())
                   return context.GetAllSamples();
         }
    }
    

    Presentation Layer:

    public class SampleController
    {
         public JsonResult Index() => new JsonResult(new SampleService().RetrieveSamples());
    }
    

    You could use Dependency Injection or whatever, but this is a basic approach to help show you how the structure is designed to work within. No solution is perfect, choose what fits your application requirements, don't add additional complexity unless it is to solve a legitimate issue, but hopefully this helps you understand.