How to get OWIN Database Context in Database First Project - c#

I've worked for days getting Identity Framework to work on my database first project. The book that I have appears only to explain how to implement it using database first, but it mentioned OWIN.
I can see from the code first version that we can get an OWIN instance of a database context by calling a static Create method on the database context that returns an instance of itself.
Isn't OWIN compatible with database first models and database contexts? If so, how do I get an instance of my database context using OWIN?
This is how you do it within code first:
Database Context
public class AppIdentityDbContext : IdentityDbContext<AppUser> {
public AppIdentityDbContext() : base("IdentityDb") {}
public static Create() {
return new AppIdentityDbContext();
}
}
Calling from OWIN start class:
app.CreatePerOwinContext<AppIdentityDbContext>(AppIdentityDbContext.Create);

I realised that the OWIN stuff isn't directly related to whether your application uses Entity Framework code first or database first.
The OWIN context is used to get to the UserManager, RoleManager etc. for ASP.NET Identity Framework. The DbContext specified in this context is really for use solely by these classes and not just for general use within your ASP.NET MVC application.
I'm now using a IoC Container to inject my DbContext into my controllers within my projects. (I'm using Ninject, but there are others such as Unity, MEF)

Related

What is the proper way to reuse DbContext across different projects in a single solution?

I have a .Net Core solution which consists of 3 projects like below:
Common : (All EF Data, migrations, Model, DbContext)
WebApi : (Rest api consuming DbContext from Common)
Worker : (Background services that aims to consume DbContext from Common)
I wanted to place all my EF logic and DbContext in Common and consume it from my other two projects.
WebApi is working fine,
but I couldn't use it from my hosted services found in Worker project.
There are 4 background workers and all of them require access to database so I wanted to get access to my DbContext inside them.
So, what is the proper way to reuse a DbContext across multiple projects.
It can be considered that all services need access some common tables. So isolating tables via different Dbcontexts is not an option for me.
This is my Startup.cs in WebApi:
services.AddDbContext<DataContext>(options => options
.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
This is my Program.cs in Worker:
services.AddDbContext<DataContext>(options => options
.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
It throws an error telling me that I can not consume a scoped service from a singleton one.
If you just want to reference a DbContext in your Web API + Background Workers, then I don't understand what the issue is: Just reference the Common project from your worker projects. From your post the issue looks to be that the service injection you are using successfully in the Web API doesn't work with the background worker services. (Assuming Windows Services?)
Start instead with a simpler scenario. Initiate the DbContext inside the service when used rather than inject it.
I.e.
using(var context = new DataContext("DefaultConnection"))
{
// ...
}
Your connection string configuration should be identifying NPGSQL as the provider so as long as that config is all set up in your Services config then the DBContext should be able to configure by connection string name. If that works then there will probably be a different mechanism for injection. From what I could quickly find it seems examples used a service locator pattern to resolve dependencies, I don't know if there are better options these days for Windows Services.
If injection isn't really an option and you have to resort to service locator-like implementations then I would probably consider something like a Lazy Property injection pattern I've used in the past:
public class WorkerService
{
private readonly IContainer _container = null;
public WorkerService(IContainer container)
{
_container = container ?? throw new ArgumentNullException("container");
}
private IDataContextFactory _contextFactory = null;
public IDataContextFactory ContextFactory
{
get { return _contextFactory ?? (_contextFactory = _container.Resolve<IDataContextFactory>()); }
set { _contextFactory = value; }
}
public void Execute()
{
using(var context = ContextFactory.Create()) // returns a DataContext.
{
// do stuff.
}
}
}
Where IContainer represents a contract interface for your given DI framework. (Unity, Autofac, etc.)
Alternatively, a unit of work for scoping a DbContext. Given a Service instance will be long running we don't want to inject or resolve a DbContext, but rather a Context Factory which we can use to receive an initialized DbContext which can be used in a dispose. Normally with web requests the instance is scoped to the request and disposed by the container at the end of the request. With a service we want to ensure the DbContext is disposed regularly. A DI can be set up so that transient instances of the context are returned, but those instances need to be disposed meaning it's not suited for constructor injection, but rather via a service locator. If a single DbContext instance was used and injected in the constructor of a service, it would live until the service stopped which would see that DbContext get slower and slower as time went on due to tracked entities.
I think you're a bit confused here. The thing you want to reuse is the DbContext code + all EF logic. You don't want to (can't) reuse same DbContext instance across projects (apps).
So to reuse the code, you just need to put all of your Model + DBContext in a project. Then in other projects, you can add reference to it. And start using it.
Remove all AddDbContext from Startup.cs/Program.cs.
Put DbContext connectionstring in Common project instead.
Create some CRUDs in Common project. Then all other projects can use Common's CRUD which is connected to same DbContext.

How to manage db context in n-tier asp.net application with dependecy injection?

I have 3-layers architecture - asp.net web api, BLL and DAL. I use Ninject as dependency injector for injecting db context and objects between layers. As ORM i use Entity Framework . Injection of db context is processed in DAL. So every time some repository in BLL is instancied, new instance of db context is also created. Im doing it like this:
public class UserRepository : IUserRepository
{
private IChatDbModel _chatDbModel;
public UserRepository(IChatDbModel chatDbModel)
{
this._chatDbModel = chatDbModel;
}
It´s neccesary to say that PerWebRequest, which would solve my problem is not availible in lower layers than web api. Only web api layer has info about http request lifetime, so can use Ninject.Web.Common library.
My question is, is there a way how to share db context for whole request like using of PerWebRequest in this architecture? Or is really neccesary to create new instance of db context for every new instance of repository?
Edit
I forgot to mention that in each layer I´m referencing Ninject library and I´m registering mapping for the specific layer. The method in DAL looks like this:
public static void Register(IKernel kernel)
{
kernel.Bind<IChatDbModel>().To<ChatDbModel>();
}
in BLL it looks like this:
public static void Register(IKernel kernel)
{
kernel.Bind<IUserRepository>().To<UserRepository>();
NinjectDataAccess.Register(kernel);
}
in API it looks like this, it´s located in NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserLogic>().To<UserLogic>();
NinjectLogic.Register(kernel);
}
so in each layer, I´m not only mapping it´s own objects but also calling register method of the layer lying below if any and with mechanism like this, I can register dependency mapping of each layer without referencing all layers in API, where I should not reference any other layer than BLL, so in my case DAL. If I reference the DAL in API layer, then it would be possible to define the mapping and call PerWebRequest, because I would have the objects, but I´m not and I think this should be avoided by the architecture, or am I wrong?
You can achieve per request instance by registering OnePerRequestHttpModule http module, which internally uses HttpContext lifecycle to track registered types and dispose them at the end of the request/response lifecycle.
After installing Ninject.Web.Common package, in NinjectWebCommon.cs you have to do (it will be added automatically once nuget package is installed)
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule))
And for your type registrations, you can do the following
//register IChatDbModel with per request scope
kernel.Bind<IChatDbModel>().To<ChatDbModel>().InRequestScope();
//register repositories with default transient scope
kernel.Bind<IUserRepository>().To<UserRepository>();
All your repositories will be transient, so everywhere they are injected , a separate instance will be supplied, but your DBContext instance will created and disposed per request.
I am assuming you have added both BAL and DAL reference to web api project, so that web api project has access to IChatDbModel to perform type registration in Ninject kernel.

Authorization using action filter and EF

I'm trying to make my own authorization filter by implementing System.Web.Http.Filters.ActionFilterAttribute so it has dependencies to repositories and user manager (they are using EF). I tried to resolve it by using Inject attribute but it injects a disposed instance (exactly same problem asked here : MVC3 Action Filter Using Database (EF 4.1 DBContext, Ninject))
So I tried to get my dependencies using bootstrapper:
public override void OnActionExecuting(HttpActionContext actionContext)
{
UserManager = (UserManager<User>)Startups.NinjectConfig.bootstrapper.Kernel.GetService(typeof(UserManager<User>));
// other repositories are same as user manager.
// check user access
base.OnActionExecuting(actionContext);
}
It works fine and I have my repository instances but it throws this exception when it gets two (or more) requests at same time:
A second operation started on this context before a previous asynchronous operation completed.
Ninject bindings are in request scope.
Why this happens and what is best way to solve this?

Putting DBContext scope to IService

I have a web app and a windows service app.
The web app injects IPersonService into its MVC controllers.
The windows app also uses IPersonService.
The service takes 3 dependencies on IPersonRepo, IAddressRepo, IEmploymentRepo for example.
The implementations of the repositories take a DBContext for Entity Framework use.
In a web app I can register the DBContext as Bind<MyContext>().ToSelf().InRequestScope();
In the windows service its trickier. I could leave it so the DBContext is transient but that seems wrong.
So I thought I could make the services be the scope to determine the life cycyle of the DBContext but am completely unsure how I would go about that to make sure it worked well for a web app and windows service app.
Any help would be greatly appreciated
If it's important that all 3 repos use the same DbContext instance, you can do something like this:
var context = new DbContext(...);
Bind<IPersonRepo>().To<PersonRepo>().WithConstructorArgument("dbContext", context);
Bind<IAddressRepo>().To<AddressRepo>().WithConstructorArgument("dbContext", context);
Bind<IEmploymentRepo>().To<EmploymentRepo>().WithConstructorArgument("dbContext", context);
Like this the same context instance is shared between the repos.
If the repositories are not aware of each other's entities (and changes to these entities), you could simply inject a fresh instance of DbContext in each repo, by binding in transient scope (default behavior):
Bind<MyContext>().ToSelf();

MVC3 & EF. Interface for TDD

Can somebody please explain:
I am using MVC3/C#/Razor to build a project to get used to using MVC.
I am using the inbuilt account controller.
I am storing the account data in my local SQL database using Entity Framework to connect.
How can I easily generate interfaces for EF?
SO FAR I am using the plugin from: http://blog.johanneshoppe.de/2010/10/walkthrough-ado-net-unit-testable-repository-generator/#step1
This allows me to have an interface for my entities already created.
However, I know that I have to change my HomeController arguments to accept either the real repository or a fake one for testing.
I am completely lost!
Have a look at these. They will help and get you started :
http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
http://msdn.microsoft.com/en-us/library/gg416511(VS.98).aspx
For dependency injection, you can follow these steps :
Install-Package Ninject.MVC3 with nuget to your ASP.NET MVC 3 project (if your app is on version 3). This will basically do everything.
Then have the following on your controller :
private IMyModelRepository _myrepo;
public HomeController(IMyModelRepository myrepo)
{
_myrepo = myrepo;
}
Go to NinjectMVC3.cs file inside App_Start folder and add the following code to inside RegisterServices method :
private static void RegisterServices(IKernel kernel) {
kernel.Bind<IMyModelRepository>().To<MyModelRepository >();
}
Fire up your app and you should be up and running.

Categories

Resources