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

.net-core asp.net-core c# entity-framework-core n-tier-architecture

Question

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?

1
2
6/8/2019 2:18:06 PM

Accepted Answer

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.

2
6/8/2019 2:36:02 PM

Popular Answer

What I am currently doing is creating an extension in my business logic project which has a reference to the data access project that encapsulates EF Core. The structure is the following:

  • API (ASP.NET Core API - references Services)
  • Services (Business Logic - References DataAccess)
  • DataAccess (EF Core Here)

In my Services project I have an extension like this:

public static class AppExtensions
{
    public static IServiceCollection SetUpAppDependencies(this IServiceCollection serviceCollection,
        string connectionString)
    {
        serviceCollection.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
        return serviceCollection;
    }
}

Then in ConfigureServices I do this:

// connectionString should come from KeyVault or Configuration
services.SetUpAppDependencies(connectionString);


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow