【发布时间】:2019-01-21 17:30:34
【问题描述】:
也许这个问题有一些解释,但找不到最好的解决方案:
我正在阅读 Mark Seemann 的这篇 blog post 关于强制依赖项的内容,据我所知,在帖子末尾,他得出结论永远不要使用或至少尝试避免强制依赖项,否则会有麻烦( 到目前为止还可以)。这是 Autofac 文档中的另一个 post。
他们建议仅根据目的(当你知道自己在做什么!)使用强制依赖。这让我想到了我网站上的情况。我有 10 个服务,它们都依赖DbContext 进行数据库操作。我认为他们可以很容易地注册为InstancePerLifetimeScope,如果我解决DbContext 的问题,而不是将其永久保存在我的服务的内存中。 (就我而言,我使用的是 Autofac)。所以,我认为一个好的起点是根据生命周期实例创建所有这些,并将DbContext 作为每个请求的实例。然后在我的服务中,我会使用类似的东西:
public class MyService
{
private readonly IDbContext _dbContext = DependencyResolver.Current.GetService<IDbContext>();
private MyModel GetMyModel() => Mapper.Map<MyModel>(_dbContext.MyTable.FirstOrDefault());
}
然后在我的启动课上我有:
builder.RegisterType<ApplicationDbContext>().As<IDbContext>().InstancePerRequest();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
此模式是否正常工作,我的意思是不要将dbContext 永远附加到任何服务,因此它将在请求结束时被处理,如果它有效,则此行是否存在任何性能问题:
private readonly IDbContext _dbContext = DependencyResolver.Current.GetService<IDbContext>();
与构造函数注入相比(从 dbContext 到数据库的调用很多,所以每次我想使用它时我都害怕得到IDbContext,因为它可能会消耗资源)?
我希望 dbContext 成为每个请求的实例而不是每个依赖项的实例的原因是我在 dbContext 对象之上实现了工作单元模式。
我的控制器中的普通方法如下所示:
public ActionResult DoSth()
{
using(var unitOfWork = UnitOfWorkManager.NewUnitOfWork())
{
//do stuff
try
{
unitOfWork.Commit();
return View();
}
catch(Exception e)
{
unitOfWork.RollBack();
LoggerService.Log(e);
return View();
}
}
}
如果这工作正常,那么还有另一个我担心的问题。因此,如果我可以将我的服务作为每个生命周期的实例(DbContext 除外),那么在服务内的每个方法上应用 async-await 以使其成为非阻塞方法是否存在任何问题。我问这个是否对 dbContext 实例使用 async-await 有任何问题,所以,例如,我会有这样的事情:
public async MyModel GetMyModel()
{
var result = //await on a new task which will use dbcontext instance here
return Mapper.Map<MyModel>(result);
}
非常感谢任何建议或建议!
【问题讨论】:
-
稍微切线您的
MyService示例是使用服务定位器作为并列显式依赖原则。 -
@Nikosi 是的,我理解,但仅在涉及 dbContext 时使用这种方式是否可以接受?
-
由于紧耦合,通常不建议这样做。尽管针对核心,您还应该阅读有关 DI docs.microsoft.com/en-us/aspnet/core/fundamentals/… 的文档中的这篇文章,重点关注 llifetime 范围部分
-
如果
MyService依赖于dbContext并且注册的生命周期比dbContext更长,那么dbContext有效注册的生命周期比MyService更长。例如如果dbContext是每个请求且MyService是单例,则dbContext被捕获,并且相对于MyService而言实际上是单例 -
请注意,对
DependencyResolver.Current.GetService<IDbContext>的调用是Service Locator anti-pattern(Mark 的博客)的实现。你应该总是更喜欢构造函数注入。
标签: c# entity-framework dependency-injection asp.net-mvc-5 autofac