Search code examples
c#asp.net-core.net-coreentity-framework-coren-tier-architecture

How can I EFCore DB Context in an N-Tier architecture with an ASP.NET Core application?


I've been trying to follow an asp.net mvc core tutorial online and I noticed that when using entity framework you can enable it in ConfigureServices in the application start up file like so:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MyContext>(cfg => cfg.UseSqlServer());
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

but what if I intend to use an n-tier architecture having different projects for the domain and data layers?

enter image description here

So I wouldn't have a reference to EntityFramework or the DBContext in my API layer as these would be separated by a domain layer?

The only solution that comes to mind is to add the Context to a "Common" project but that doesn't feel like the right thing to do?

How would you guys solve this?


Solution

  • This problem is negligible in terms of architecture, but if you are really concerned about separating the EF dependencies into a separate project then you can just separate the dependency injection layer alltogether into separate project and use reference only to that in multiple other projects.

    EDIT: I may not have been elaborate enough on this so here is an example of what I meant. I assume your Example.Domain has some repository which references the your EF YourDbContext

    public class YourDomainRepository
    {
        private readonly YourDbContext _context;
    
        public YourDomainRepository(YourDbContext context)
        {
            _context = context;
        }
    
        ...Other repository methods
    }
    

    The issue you are describing is that it's not enough to just reference the Example.Domain in your Example.Api because in order for the DI to work you need to add it to the services and you need to add both YourDomainRepository and other services on which it depends (like YourDbContext) which in turns what requires you to reference EF libraries.

    So the approach I tried to propose is either:

    • Option 1 - you create another project for common stuff like DI. That project would house a function like below:

      public static class YourDomainDIExtensions
      {
          public static void AddDomainDataServices(this IServiceCollection services)
          {
              services.AddDbContext<YourDbContext>(...);
              services.AddTransient<YourDomainRepository>();
          }
      }
      
    • Option 2 - you don't create a new project and just have the same extension class in your domain project.

    Either way this abstracts the EF dependencies from your Example.API and in there you will just call:

    services.AddDomainDataServices();
    

    Which effectively is reusable across multiple projects.