Dependency Injected DbContext is always null
I've used DI across multiple ASP.NET (Core) applications where DbContext is injected into a controller constructor, and upon the first request to the controller, the constructor is ran and the dependency injected.
I'm now working with a web API project that is hooked into an Azure Message Bus, processing and persisting data from the bus and providing an API endpoint for the data. The class processing and persisting the messages from Azure Message Bus is QueueProcessor.
I need to persist the data from project start, which means I need an instance of DbContext from when the project is ran as opposed to when I'm querying data out via an API endpoint. Due to this, the constructor of QueueProcessor is never implicitly called, and if I want to manually do so I need a pre-existing instance of MyDbContext to pass to it.
I've been researching this for a couple of days, trying out some manual patterns but I'm running into concurrency issues and the whole project feels like a hack at the moment.
The closest question I've come across is this, which despite specifying non-controllers, the accepted answer requires a controller for the dependency to be injected.
This is what I'm currently doing:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
I'm then having to create a new instance of my QueueProcessor and use var context = new MyDbContext() inside the constructor. This is causing concurrency issues and completely negates the DI.
If I want to inject MyDbContext with DI like I have done hundreds of times, creating an instance of the class to run a process inside the QueueProcessor means I have to pass an instance of MyDbContext to the constructor myself. VS flags this up at design time.
I've ever tried botching this as much as possible by doing:
services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));
I'm looking for a cleaner way of achieving:
- Invoke a method inside
QueueProcessorto handle Azure Message Bus messages from project start. - Before messages are processed, I should have an instantiated instance of
MyDbContextthat I can use to persist the messages when they get processed. - Not have to use a
Controllerto set up the DI correctly.
Is there a way to achieve this or have I completely missed the mark here?
c# entity-framework
add a comment |
I've used DI across multiple ASP.NET (Core) applications where DbContext is injected into a controller constructor, and upon the first request to the controller, the constructor is ran and the dependency injected.
I'm now working with a web API project that is hooked into an Azure Message Bus, processing and persisting data from the bus and providing an API endpoint for the data. The class processing and persisting the messages from Azure Message Bus is QueueProcessor.
I need to persist the data from project start, which means I need an instance of DbContext from when the project is ran as opposed to when I'm querying data out via an API endpoint. Due to this, the constructor of QueueProcessor is never implicitly called, and if I want to manually do so I need a pre-existing instance of MyDbContext to pass to it.
I've been researching this for a couple of days, trying out some manual patterns but I'm running into concurrency issues and the whole project feels like a hack at the moment.
The closest question I've come across is this, which despite specifying non-controllers, the accepted answer requires a controller for the dependency to be injected.
This is what I'm currently doing:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
I'm then having to create a new instance of my QueueProcessor and use var context = new MyDbContext() inside the constructor. This is causing concurrency issues and completely negates the DI.
If I want to inject MyDbContext with DI like I have done hundreds of times, creating an instance of the class to run a process inside the QueueProcessor means I have to pass an instance of MyDbContext to the constructor myself. VS flags this up at design time.
I've ever tried botching this as much as possible by doing:
services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));
I'm looking for a cleaner way of achieving:
- Invoke a method inside
QueueProcessorto handle Azure Message Bus messages from project start. - Before messages are processed, I should have an instantiated instance of
MyDbContextthat I can use to persist the messages when they get processed. - Not have to use a
Controllerto set up the DI correctly.
Is there a way to achieve this or have I completely missed the mark here?
c# entity-framework
add a comment |
I've used DI across multiple ASP.NET (Core) applications where DbContext is injected into a controller constructor, and upon the first request to the controller, the constructor is ran and the dependency injected.
I'm now working with a web API project that is hooked into an Azure Message Bus, processing and persisting data from the bus and providing an API endpoint for the data. The class processing and persisting the messages from Azure Message Bus is QueueProcessor.
I need to persist the data from project start, which means I need an instance of DbContext from when the project is ran as opposed to when I'm querying data out via an API endpoint. Due to this, the constructor of QueueProcessor is never implicitly called, and if I want to manually do so I need a pre-existing instance of MyDbContext to pass to it.
I've been researching this for a couple of days, trying out some manual patterns but I'm running into concurrency issues and the whole project feels like a hack at the moment.
The closest question I've come across is this, which despite specifying non-controllers, the accepted answer requires a controller for the dependency to be injected.
This is what I'm currently doing:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
I'm then having to create a new instance of my QueueProcessor and use var context = new MyDbContext() inside the constructor. This is causing concurrency issues and completely negates the DI.
If I want to inject MyDbContext with DI like I have done hundreds of times, creating an instance of the class to run a process inside the QueueProcessor means I have to pass an instance of MyDbContext to the constructor myself. VS flags this up at design time.
I've ever tried botching this as much as possible by doing:
services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));
I'm looking for a cleaner way of achieving:
- Invoke a method inside
QueueProcessorto handle Azure Message Bus messages from project start. - Before messages are processed, I should have an instantiated instance of
MyDbContextthat I can use to persist the messages when they get processed. - Not have to use a
Controllerto set up the DI correctly.
Is there a way to achieve this or have I completely missed the mark here?
c# entity-framework
I've used DI across multiple ASP.NET (Core) applications where DbContext is injected into a controller constructor, and upon the first request to the controller, the constructor is ran and the dependency injected.
I'm now working with a web API project that is hooked into an Azure Message Bus, processing and persisting data from the bus and providing an API endpoint for the data. The class processing and persisting the messages from Azure Message Bus is QueueProcessor.
I need to persist the data from project start, which means I need an instance of DbContext from when the project is ran as opposed to when I'm querying data out via an API endpoint. Due to this, the constructor of QueueProcessor is never implicitly called, and if I want to manually do so I need a pre-existing instance of MyDbContext to pass to it.
I've been researching this for a couple of days, trying out some manual patterns but I'm running into concurrency issues and the whole project feels like a hack at the moment.
The closest question I've come across is this, which despite specifying non-controllers, the accepted answer requires a controller for the dependency to be injected.
This is what I'm currently doing:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
I'm then having to create a new instance of my QueueProcessor and use var context = new MyDbContext() inside the constructor. This is causing concurrency issues and completely negates the DI.
If I want to inject MyDbContext with DI like I have done hundreds of times, creating an instance of the class to run a process inside the QueueProcessor means I have to pass an instance of MyDbContext to the constructor myself. VS flags this up at design time.
I've ever tried botching this as much as possible by doing:
services.AddTransient(x => new QueueProcessor(x.GetService<MyDbContext>(), Configuration.GetConnectionString("MessageBus")));
I'm looking for a cleaner way of achieving:
- Invoke a method inside
QueueProcessorto handle Azure Message Bus messages from project start. - Before messages are processed, I should have an instantiated instance of
MyDbContextthat I can use to persist the messages when they get processed. - Not have to use a
Controllerto set up the DI correctly.
Is there a way to achieve this or have I completely missed the mark here?
c# entity-framework
c# entity-framework
asked Nov 28 '18 at 10:30
Jay GouldJay Gould
1,7071124
1,7071124
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
A working solution, not sure if it's the best pattern:
- In
Startup.cschanceConfigureServicesto returnIServiceProviderrather thanvoid. - Build the serviceProvider using:
var serviceProvider = services.BuildServiceProvider();
- Get the instance of MyDbContext:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- Create an instance of
QueueProcessorand passcontextto the constructor and invoke method to begin processing messages. - From
ConfigureServices, return your newserviceProvider.
Full code block:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53517321%2fdependency-injected-dbcontext-is-always-null%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
A working solution, not sure if it's the best pattern:
- In
Startup.cschanceConfigureServicesto returnIServiceProviderrather thanvoid. - Build the serviceProvider using:
var serviceProvider = services.BuildServiceProvider();
- Get the instance of MyDbContext:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- Create an instance of
QueueProcessorand passcontextto the constructor and invoke method to begin processing messages. - From
ConfigureServices, return your newserviceProvider.
Full code block:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
add a comment |
A working solution, not sure if it's the best pattern:
- In
Startup.cschanceConfigureServicesto returnIServiceProviderrather thanvoid. - Build the serviceProvider using:
var serviceProvider = services.BuildServiceProvider();
- Get the instance of MyDbContext:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- Create an instance of
QueueProcessorand passcontextto the constructor and invoke method to begin processing messages. - From
ConfigureServices, return your newserviceProvider.
Full code block:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
add a comment |
A working solution, not sure if it's the best pattern:
- In
Startup.cschanceConfigureServicesto returnIServiceProviderrather thanvoid. - Build the serviceProvider using:
var serviceProvider = services.BuildServiceProvider();
- Get the instance of MyDbContext:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- Create an instance of
QueueProcessorand passcontextto the constructor and invoke method to begin processing messages. - From
ConfigureServices, return your newserviceProvider.
Full code block:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
A working solution, not sure if it's the best pattern:
- In
Startup.cschanceConfigureServicesto returnIServiceProviderrather thanvoid. - Build the serviceProvider using:
var serviceProvider = services.BuildServiceProvider();
- Get the instance of MyDbContext:
var context = serviceProvider.GetRequiredService<MyDbContext>();
- Create an instance of
QueueProcessorand passcontextto the constructor and invoke method to begin processing messages. - From
ConfigureServices, return your newserviceProvider.
Full code block:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("...")));
var serviceProvider = services.BuildServiceProvider();
var localMyDbContext = serviceProvider.GetRequiredService<MyDbContext>();
Processor = new QueueProcessor(localDbContext, Configuration.GetConnectionString("Other"));
Processor.RunAsync().GetAwaiter().GetResult();
return serviceProvider;
}
edited Dec 5 '18 at 9:15
answered Nov 28 '18 at 11:07
Jay GouldJay Gould
1,7071124
1,7071124
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53517321%2fdependency-injected-dbcontext-is-always-null%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown