如何在 n 层存储库模式中共享 DbCOntext。 Asp.net MVC
How to share a DbCOntext in n-tier repository pattern. Asp .net mvc
首先我必须说,我知道他们是我在 Whosebug 上发现的一个非常接近的问题,但我的问题有点不同。
我在 asp .net mvc 中有 n 层应用程序,其中我有:
A BOL 项目(有 EF 类 和 db 对象等),
BLL 项目(有商业逻辑),
比我们有 DAL 项目(它有数据库交互逻辑,它使用来自 BOL 的 EF dbcontext)。
还有一个 主 mvc 项目 其中包含控制器和视图等
现在,我们正在使用存储库模式,我们在 BLL 中有许多存储库及其接口。而且我们在 DAL 中还有 许多没有接口的存储库 。但是 所有这些 DAL 存储库中都有一个 DbContext 成员,这是在它们的构造函数中创建的,因此 每个 DAL 存储库都与它拥有的单独的 DbContext 实例进行交互已创建。
在我们的主要 mvc 项目中,我们 使用 ninject 将 BLL 存储库注入控制器构造函数 (在请求范围内)。现在,我们面临的问题 是,每个 BLL 存储库都有对一个或多个 DAL 存储库的引用,并且 每个 DAL 存储库都在使用它们自己单独的 DbCOntext。这是错误和错误的,这就是为什么我正在寻找在所有 DAL 存储库中共享一个 DbCOntext 的方法,每个请求(无论有多少 BLL 存储库 ninject 在我的控制器中注入,只需确保只有一个 DbContext 实例是根据请求创建和使用)。并在每次请求后处理该上下文。
我认为的一种方法是不在 DAL 存储库的构造函数中创建 DBcontext。但是有一些方法调用(比如 initiateDbContext),而不是在 BLL 存储库中添加这个方法,它除了调用其成员 DAL 存储库的 smae 方法之外什么都不做。在控制器构造函数中为 one BLL 存储库调用该方法,然后有一个方法可以从第一个存储库获取和设置所有其他存储库中的数据库上下文。但我知道这是不好的方法,首先我们在控制器中创建 DbContext,它应该只在 DAL 中,其次我在 DAL 和 BLL 存储库中添加创建、获取和设置 DbCOntext 方法,因为我需要将 DbCOntext 传递给BLL 会将其传递给它在内部通信的 DAL 存储库。这很糟糕。
这就是为什么我在这里询问 任何好的模式来实现 "ONE DBCONTEXT PER REQUEST IN N-TIER WITH REPOSITORY PATTERN."
You can write one BaseRepository and implement BaseRepository in all repository classes.
public class BaseRepository
{
public StudentEntities dbStudentEntity;
public BaseRepository()
{
dbStudentEntity = new StudentEntities();
}
}
DataRepository :
public class CurrencyData : BaseRepository,ICurrencyData
{
public List<Models.Currency> GetCurrencyList()
{
var objCurrencies = dbStudentEntity.Currencies.ToList();
List<Models.Currency> currencyList = new List<Models.Currency>();
foreach (var item in objCurrencies)
{
var model = new Models.Currency { CurrencyId = item.CurrencyId, Currency1 = item.Currency1,Code = item.Code,Symbol = item.Symbol,Country = item.Country };
currencyList.Add(model);
}
return currencyList;
}
}
如果你在使用依赖注入,你应该一路使用它,而不仅仅是在控制器中。
这意味着,应该将 DBContext 注入到存储库中,并且 Ninject 应该配置为在每个请求生命周期内解析您的 DBContext。
根据 @atika 的回答,我进一步搜索并实现了他的建议(在整个应用程序中使用 ninject/DI 而不仅仅是在 mvc 的一个主要项目中)它解决了这个问题,我发布这个答案是为了添加更多细节和我遇到的一些额外问题,我不得不花时间进一步谷歌搜索,这样其他人可能会节省一些时间。
想法是在整个解决方案中使用依赖注入,无论你有多少projects/tiers,也不管你有多少存储库。
所以,问题来了,如果我们想使用 ninject 或任何其他 DI 来绑定所有 tiers/projects 的所有依赖项,我们应该参考到我们的主要 mvc 项目中的所有那些 tiers/projects,以便我们可以绑定 NinjectWebCommons 中的依赖项,但这会破坏 n 层架构的全部目的。我们不想那样做,我们希望我们的等级制度能够维持下去,就像我的情况一样
MainMVCProject->BLL->DLL->DB
因此,为此,我找到了一篇非常有用的文章 Ninject with N-Tier MVC Application - Inject Object in Business Layer。(它们还有一些其他方法,一种是创建一个仅用于绑定的项目并将该项目添加到绑定所有依赖项,但这听起来像是过度工程和矫枉过正)
基于此,我在我的 BLL tier/project 中添加了以下 class(在此项目和 DAL 项目中安装 ninject 之后),它具有 DLL 的绑定 classes.
using BLL.Repositories;
using BLL.RepositoryInterfaces;
using Ninject.Modules;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL;
using BOL;
namespace BLL
{
public class LayerBindings : NinjectModule
{
public override void Load()
{//add all references here like these
Bind<AdDb>().ToSelf().InRequestScope();
Bind<db_Entities>().ToSelf().InRequestScope().WithConstructorArgument("ConnectionString", BOL.CommonFunctionsBOL.ConnectionString);
}
}
}
从 howto-ninject-part-1-basics 文章中得到一些帮助,我设法用 ninject 做了很多事情,并使用了它的许多功能。
现在,您可以看到我在此class中添加了 DLL 项目的绑定,这在主 mvc 项目中是不可访问的。现在,我只需要在 main ninject 中加载这些绑定。
现在,在 NinjectWebCommons.cs 文件中,我添加了以下行:
//old bindings of BLL and local project.
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
//now here we bind other dependencies of DAL etc using class we added in BLL
var modules = new List<INinjectModule>
{
new BLL.LayerBindings()
};
kernel.Load(modules);
(在 RegisterServices 方法中,在本地绑定和 BLL 对象绑定之后。)
这样做之后,ninject 开始在所有项目中工作,我只是使用构造函数注入或在某些地方,属性 注入并且一切正常。
PS1:我也用了属性注入*(我读到这个不推荐给使用 属性 注入,仅在不能使用构造函数注入的地方使用它们。)* 对于私有属性,必须使用 kernel.Settings.InjectNonPublic = true 启用它们; "CreateKernel" 方法中的行在 return 内核之前。
现在我的 属性 注入也适用于私有属性,如下所示:
[Ninject.Inject]
private SomeDALObject db { get; set; }
PS2: 我还为 ninject 安装了 ninject.web.webapi nuget 包webapis,并且 发现这条线可以从 ninject 的任何地方获取对象。(我不知道这是否是一个好方法,但它确实 return 一个我用过的完全构建的对象。如果有人能澄清或纠正我是否正确使用它,那就太好了。)
((TypeOfObjectYouWant)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(TypeOfObjectYouWant))).DoSomething();
我希望这可以帮助像我这样的人在这个问题上寻找合适的指南。
首先我必须说,我知道他们是我在 Whosebug 上发现的一个非常接近的问题,但我的问题有点不同。
我在 asp .net mvc 中有 n 层应用程序,其中我有:
A BOL 项目(有 EF 类 和 db 对象等),
BLL 项目(有商业逻辑),
比我们有 DAL 项目(它有数据库交互逻辑,它使用来自 BOL 的 EF dbcontext)。
还有一个 主 mvc 项目 其中包含控制器和视图等
现在,我们正在使用存储库模式,我们在 BLL 中有许多存储库及其接口。而且我们在 DAL 中还有 许多没有接口的存储库 。但是 所有这些 DAL 存储库中都有一个 DbContext 成员,这是在它们的构造函数中创建的,因此 每个 DAL 存储库都与它拥有的单独的 DbContext 实例进行交互已创建。
在我们的主要 mvc 项目中,我们 使用 ninject 将 BLL 存储库注入控制器构造函数 (在请求范围内)。现在,我们面临的问题 是,每个 BLL 存储库都有对一个或多个 DAL 存储库的引用,并且 每个 DAL 存储库都在使用它们自己单独的 DbCOntext。这是错误和错误的,这就是为什么我正在寻找在所有 DAL 存储库中共享一个 DbCOntext 的方法,每个请求(无论有多少 BLL 存储库 ninject 在我的控制器中注入,只需确保只有一个 DbContext 实例是根据请求创建和使用)。并在每次请求后处理该上下文。
我认为的一种方法是不在 DAL 存储库的构造函数中创建 DBcontext。但是有一些方法调用(比如 initiateDbContext),而不是在 BLL 存储库中添加这个方法,它除了调用其成员 DAL 存储库的 smae 方法之外什么都不做。在控制器构造函数中为 one BLL 存储库调用该方法,然后有一个方法可以从第一个存储库获取和设置所有其他存储库中的数据库上下文。但我知道这是不好的方法,首先我们在控制器中创建 DbContext,它应该只在 DAL 中,其次我在 DAL 和 BLL 存储库中添加创建、获取和设置 DbCOntext 方法,因为我需要将 DbCOntext 传递给BLL 会将其传递给它在内部通信的 DAL 存储库。这很糟糕。
这就是为什么我在这里询问 任何好的模式来实现 "ONE DBCONTEXT PER REQUEST IN N-TIER WITH REPOSITORY PATTERN."
You can write one BaseRepository and implement BaseRepository in all repository classes.
public class BaseRepository
{
public StudentEntities dbStudentEntity;
public BaseRepository()
{
dbStudentEntity = new StudentEntities();
}
}
DataRepository :
public class CurrencyData : BaseRepository,ICurrencyData
{
public List<Models.Currency> GetCurrencyList()
{
var objCurrencies = dbStudentEntity.Currencies.ToList();
List<Models.Currency> currencyList = new List<Models.Currency>();
foreach (var item in objCurrencies)
{
var model = new Models.Currency { CurrencyId = item.CurrencyId, Currency1 = item.Currency1,Code = item.Code,Symbol = item.Symbol,Country = item.Country };
currencyList.Add(model);
}
return currencyList;
}
}
如果你在使用依赖注入,你应该一路使用它,而不仅仅是在控制器中。
这意味着,应该将 DBContext 注入到存储库中,并且 Ninject 应该配置为在每个请求生命周期内解析您的 DBContext。
根据 @atika 的回答,我进一步搜索并实现了他的建议(在整个应用程序中使用 ninject/DI 而不仅仅是在 mvc 的一个主要项目中)它解决了这个问题,我发布这个答案是为了添加更多细节和我遇到的一些额外问题,我不得不花时间进一步谷歌搜索,这样其他人可能会节省一些时间。
想法是在整个解决方案中使用依赖注入,无论你有多少projects/tiers,也不管你有多少存储库。
所以,问题来了,如果我们想使用 ninject 或任何其他 DI 来绑定所有 tiers/projects 的所有依赖项,我们应该参考到我们的主要 mvc 项目中的所有那些 tiers/projects,以便我们可以绑定 NinjectWebCommons 中的依赖项,但这会破坏 n 层架构的全部目的。我们不想那样做,我们希望我们的等级制度能够维持下去,就像我的情况一样
MainMVCProject->BLL->DLL->DB
因此,为此,我找到了一篇非常有用的文章 Ninject with N-Tier MVC Application - Inject Object in Business Layer。(它们还有一些其他方法,一种是创建一个仅用于绑定的项目并将该项目添加到绑定所有依赖项,但这听起来像是过度工程和矫枉过正)
基于此,我在我的 BLL tier/project 中添加了以下 class(在此项目和 DAL 项目中安装 ninject 之后),它具有 DLL 的绑定 classes.
using BLL.Repositories;
using BLL.RepositoryInterfaces;
using Ninject.Modules;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL;
using BOL;
namespace BLL
{
public class LayerBindings : NinjectModule
{
public override void Load()
{//add all references here like these
Bind<AdDb>().ToSelf().InRequestScope();
Bind<db_Entities>().ToSelf().InRequestScope().WithConstructorArgument("ConnectionString", BOL.CommonFunctionsBOL.ConnectionString);
}
}
}
从 howto-ninject-part-1-basics 文章中得到一些帮助,我设法用 ninject 做了很多事情,并使用了它的许多功能。
现在,您可以看到我在此class中添加了 DLL 项目的绑定,这在主 mvc 项目中是不可访问的。现在,我只需要在 main ninject 中加载这些绑定。 现在,在 NinjectWebCommons.cs 文件中,我添加了以下行:
//old bindings of BLL and local project.
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
//now here we bind other dependencies of DAL etc using class we added in BLL
var modules = new List<INinjectModule>
{
new BLL.LayerBindings()
};
kernel.Load(modules);
(在 RegisterServices 方法中,在本地绑定和 BLL 对象绑定之后。)
这样做之后,ninject 开始在所有项目中工作,我只是使用构造函数注入或在某些地方,属性 注入并且一切正常。
PS1:我也用了属性注入*(我读到这个不推荐给使用 属性 注入,仅在不能使用构造函数注入的地方使用它们。)* 对于私有属性,必须使用 kernel.Settings.InjectNonPublic = true 启用它们; "CreateKernel" 方法中的行在 return 内核之前。
现在我的 属性 注入也适用于私有属性,如下所示:
[Ninject.Inject]
private SomeDALObject db { get; set; }
PS2: 我还为 ninject 安装了 ninject.web.webapi nuget 包webapis,并且 发现这条线可以从 ninject 的任何地方获取对象。(我不知道这是否是一个好方法,但它确实 return 一个我用过的完全构建的对象。如果有人能澄清或纠正我是否正确使用它,那就太好了。)
((TypeOfObjectYouWant)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(TypeOfObjectYouWant))).DoSomething();
我希望这可以帮助像我这样的人在这个问题上寻找合适的指南。