8

I have implemented the EntityFrameworkFileProvider for my ASP.NET core web application, I want the ViewDbContext instance to be injected by ASP.NET core DI framework in the constructor:

(ViewDbContext is a dbContext)

public class EntityFrameworkFileProvider : IFileProvider
{
    private ViewDbContext _context;

    public EntityFrameworkFileProvider(ViewDbContext context)
    { 
       /* should be injected by asp.net core DI */
        _context = context;
    }
    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        .....
    }

    public IFileInfo GetFileInfo(string subpath)
    {
        var result = new DatabaseFileInfo(_context, subpath);
        return result.Exists ? result as IFileInfo : new NotFoundFileInfo(subpath);
    }

    public IChangeToken Watch(string filter)
    {
        return new DatabaseChangeToken(_context, filter);
    }
}

Now I add the EntityFrameworkFileProvider to RazorViewEngineOption in startup.cs How to make the ViewDbContext instance to be automatically injected by DI framework in the ConfigureServices method of startup.cs? how should i call the EntityFrameworkFileProvider constructor correctly?

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
      /* Add  EntityFrameworkFileProvider to Razor engine */
      services.Configure<RazorViewEngineOptions>(opts =>
      {
          opts.FileProviders.Add(new EntityFrameworkFileProvider(null?));
      });

      services.AddMvc();
}

2 Answers 2

22

i think i have found the solution! any idea?

public void ConfigureServices(IServiceCollection services)
{
     services.AddDbContext<ViewDbContext>(options => 
       options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    ...
     /* Add  EntityFrameworkFileProvider to Razor engine */       
     var context = services.BuildServiceProvider()
                       .GetService<ViewDbContext>();

     services.Configure<RazorViewEngineOptions>(opts =>
     {
         opts.FileProviders.Add(new EntityFrameworkFileProvider(context));
     });

     services.AddMvc();
}
Sign up to request clarification or add additional context in comments.

6 Comments

Using your approach, doesn't it mean the same context object is used again and again... each time the framework wants to retrieve file details or check if a file has changed. This could effectively give you a memory leak if the context is tracking objects. The samples I have seen use a new DB Context for each call.
Piers Lawson: what do you mean, can you provide example please ?
@PiersLawson I don't think the context is storing a singleton of the ViewDbContext. It would probably instantiate based on the existing configuration for that type, i.e. AddDbContext on line 3 of the snippet above.
warning, BuildServiceProvider() results in additional copies of all Singleton services being created.
I don't know how much of a difference this makes, but I am required to build an Angular front end to this app. Razor won't be involved unless I can hide it some place.
|
5

A better approach would be to inject the context in Configure method and use it it there

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ViewDbContext context)
{
     services.AddDbContext<ViewDbContext>(options => 
       options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    ...
     /* Add  EntityFrameworkFileProvider to Razor engine */       
     /* Use db context here*/

     services.Configure<RazorViewEngineOptions>(opts =>
     {
         opts.FileProviders.Add(new EntityFrameworkFileProvider(context));
     });

     services.AddMvc();
}

2 Comments

I don't get this. Services are added in the ConfigureServices function, not the Configure function. Is this a typo, or is something going on I don't understand.
@EoRaptor013 Add private IServiceCollection _services; to the top of Startup, assign it _services = services; in ConfigureServices(IServiceCollection services){ ... }, then call _services as you like from Configure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.