简体   繁体   English

如何使用Dependecy注入管理n层asp.net应用程序中的数据库上下文?

[英]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. 我有3层架构-asp.net Web API,BLL和DAL。 I use Ninject as dependency injector for injecting db context and objects between layers. 我使用Ninject作为依赖注入器,在层之间注入数据库上下文和对象。 As ORM i use Entity Framework . 作为ORM,我使用Entity Framework。 Injection of db context is processed in DAL. db上下文的注入在DAL中处理。 So every time some repository in BLL is instancied, new instance of db context is also created. 因此,每当实例化BLL中的某个存储库时,也会创建db上下文的新实例。 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. 可以肯定地说,可以解决我的问题的PerWebRequest在低于Web api的较低层中不可用。 Only web api layer has info about http request lifetime, so can use Ninject.Web.Common library. 仅Web api层具有有关http请求生存期的信息,因此可以使用Ninject.Web.Common库。

My question is, is there a way how to share db context for whole request like using of PerWebRequest in this architecture? 我的问题是,有没有一种方法可以像在这种体系结构中使用PerWebRequest一样为整个请求共享数据库上下文? 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. 我忘了提到,在每个层中,我都引用Ninject库,并且为特定层注册映射。 The method in DAL looks like this: DAL中的方法如下所示:

    public static void Register(IKernel kernel)
    {
        kernel.Bind<IChatDbModel>().To<ChatDbModel>();
    }

in BLL it looks like this: 在BLL中,它看起来像这样:

    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: 在API中,它看起来像这样,位于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. 因此在每一层中,我不仅要映射其自己的对象,还要调用位于其下方的该层的注册方法(如果有的话),并且使用这样的机制,我可以注册每一层的依赖关系映射而无需引用API中的所有层,其中除了BLL之外,我不应引用其他任何层,因此在我的情况下为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? 如果我在API层中引用DAL,则可以定义映射并调用PerWebRequest,因为我有对象,但是我不是,我认为应该由体系结构避免这种情况,还是我错了?

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. 您可以通过注册OnePerRequestHttpModule http模块来实现每个请求实例,该模块在内部使用HttpContext生命周期来跟踪已注册的类型并将其在请求/响应生命周期的末尾进行处置。

After installing Ninject.Web.Common package, in NinjectWebCommon.cs you have to do (it will be added automatically once nuget package is installed) 安装Ninject.Web.Common软件包后,您必须在NinjectWebCommon.cs中进行操作(一旦安装了nuget软件包,它将自动添加)

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. 您所有的存储库都是临时的,因此在注入它们的任何地方,都将提供一个单独的实例,但是您的DBContext实例将根据请求创建和处置。

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. 我假设您已经向Web api项目添加了BAL和DAL引用,以便Web api项目可以访问IChatDbModel以在Ninject内核中执行类型注册。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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