简体   繁体   中英

Using DI in AspNET Core

I have a derived class of DbContext, called NavigationContext, that looks like this:

public class NavigationContext : DbContext
{
    private readonly IConfiguration _configuration;

    public NavigationContext(DbContextOptions<NavigationContext> options, IConfiguration configuration) : base(options)
    {
        _configuration = configuration;
    }
    //DbSets here ...

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_configuration.GetConnectionString("NavigationLoggingDatabase"));
        }
    }
}

The Configuration is registered to the DI container in Startup.cs, like this:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        services.AddDbContext<NavigationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("NavigationLoggingDatabase")));
        services.AddSingleton(_ => Configuration);
    }

My question is what do I send to the NavigationContext constructor?

    public int Add(TEntity item)
    {
        using (NavigationContext context = new NavigationContext(_contextOptionsBuilder.Options, ???))
        {
            context.Set<TEntity>().Add(item);
            context.SaveChanges();
            return item.Id;
        }
    }

That's not how you do DI (Dependency Injection). Whenever you see the new keyword for a service, you have to know it's wrong.

First, you don't have to pass in anything to the DbContext, that OnConfiguring override shouldn't be there as you are not using it. This call takes care of that configuration:

services.AddDbContext<NavigationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("NavigationLoggingDatabase")));

Secondly, you don't use using with injected dependencies, so:

public int Add(TEntity item)
{
    _context.Set<TEntity>().Add(item);
    _context.SaveChanges();
    return item.Id;
}

And, for this to work:

public class SomeController : Controller
{
    private readonly NavigationContext _context;

    public SomeController(NagivationContext context)
    {
        _context = context;
    }
}

And, as a last advice, you should really, really, use the asynchronous versions of the Entity Framework Core methods as much as possible:

public async Task<int> Add(TEntity item)
{
    _context.Set<TEntity>().Add(item);
    await _context.SaveChangesAsync();
    return item.Id;
}

You don't use new NavigationContext(...) at all, you're completely missing the point of dependency injection if you do that. Instead you should be injecting the context into the class that needs it. For example, if you need it directly in your controller, that would look something like this:

public class FunkyController : Controller
{
    private readonly NavigationContext _nagivationContext;

    public FunkyController(NagivationContext nagivationContext)
    {
        //Context is injected into the constructor of the controller
        _nagivationContext = nagivationContext;
    }

    public int Add(TEntity item)
    {
        _nagivationContext.Set<TEntity>().Add(item);
        _nagivationContext.SaveChanges();
        return item.Id;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM