Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid injecting concrete database context class to controller [closed]

I am using Entity Framework Core for MySql with Database first approach.

After scaffolding the database, it generates the context class: sakilaContext.cs(sakila is the built-in database/scheme in MySql, I use it for playing around).

I have my database injected in Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        var connectionString = @"server=localhost;port=1123;user=root;password=xxx;database=sakila";
        services.AddDbContext<sakilaContext>(options => options.UseMySql(connectionString));
    }

In my api controller, I do it like this:

private sakilaContext dbCtx;

public SakilaController(sakilaContext dbContext)
{
    dbCtx = dbContext;
}

Just wonder,

  1. is it wrong to inject a concrete implementation in this case??
  2. If it is, how can I just inject an interface rather than inject a concrete implementation?

Thanks

like image 621
Franva Avatar asked Nov 26 '25 19:11

Franva


1 Answers

is it wrong to inject a concrete implementation in this case??

It depends. If you're writing a multi-tier application with separated concerns (business logic, validation, authorization) or are you writing a 5 page application to display misc information for a limited number of users?

I've done exactly that for small, mostly readonly, applications because there are only small changes and I don't need to Over design and architect the solution.

If it is, how can I just inject an interface rather than inject a concrete implementation?

Sure, however at some point a class will need a dbcontext, which could be DI'd or created by the object that needs it. If you do abstract away the Data Access into a separate class/interface, I wouldn't recommend DI (to inject the context into the concrete data access) because that concrete type will be tighly coupled to EF. Meaning if you decided to switch to Dapper, NHibernate or some other ORM you'll have to rewrite all the methods anyway.

A quick and dirty way (for small/learning experiences, I would not ever recommend this for large million user systems) to abstract away the DbContext is as simple as:

public interface IUserDA
{
  IQueryable<User> Users { get; }
}

public class MyDbContext : IUserDA
{
  public DbSet<User> Users { get; set; }

  IQueryable<User> IUserDA.Users
  {
     get
     {
        return Users;  // references the DbSet
     }
  }

}

Now your MyDbContext implements an interface that is not coupled to Entity Framework.

But if we inject a concrete class, does it defeat the DI purpose?

Depends on your purpose. What exactly are you looking to achieve by using DI? Are you actually going to write real unit tests? Do you honestly see yourself changing or having multiple instances of the interfaces for multiple installation/tenants?

like image 57
Erik Philips Avatar answered Nov 29 '25 09:11

Erik Philips



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!