我目前正在使用 EF 6 设置 .NET Core 应用程序,但在理解如何正确使用各种依赖项注册方法时遇到了一些困难。据我了解:
特别是在我的情况下,我设置了一对 DbContext(基于 CQRS 模式)来处理我注册为 Scoped 的数据库查询/命令:
services.AddScoped((_) => new TestCommandContext(Configuration["Data:TestConnection:ConnectionString"]));
services.AddScoped((_) => new TestQueryContext(Configuration["Data:TestConnection:ConnectionString"]));
这是根据 ASP.NET Getting Started with ASP.NET 5 and Entity Framework 6 文档:
Context should be resolved once per scope to ensure performance and ensure reliable operation of Entity Framework
然后我将注册相应的 UOW 类(class):
services.AddTransient<ITestCommandUnit, TestCommandUnit>();
services.AddTransient<ITestQueryUnit, TestQueryUnit>();
我在这里使用 Transient 基于 this文章,这表明:
Services registered with Transient scope are created whenever it is needed within the application. That means a new instance of the (registered service) class will be created by the dependency injection framework every time the (method in which the dependency is created) is executed.
基于这种理解,我也在 Scoped 下注册我的存储库和服务类:
services.AddScoped<ITestCommandRepository, TestCommandRepository>();
services.AddScoped<ITestQueryRepository, TestQueryRepository>();
services.AddScoped<ITestCommandService, TestCommandService>();
services.AddScoped<ITestQueryService, TestQueryService>();
然后根据需要在我的 Controller 中调用我各自的服务层方法:
public class TestController : BaseController
{
private ITestQueryService testQueryService;
// Get new object of type TestQueryService via DI
public TestController(ITestQueryService testQueryService)
{
this.testQueryService = testQueryService;
}
[HttpGet]
public IActionResult Edit(int id)
{
if (id > 0)
{
EditViewModel viewModel = new EditViewModel();
viewModel.TestObject = testQueryService.GetById(id);
return View(viewModel);
}
else
{
return RedirectToAction("Error", new { errorMessage = "No object with the specified Id could be found." });
}
}
}
在测试中,此配置似乎有效,将 DbContext 设置为 Scoped 很有意义 - 每次请求时都创建一个新的上下文对象似乎没有必要/效率低下。
但是,对于其他对象,在Transient/Singleton/Scoped 之间的选择是我迷失的地方。有人可以帮助我了解这种特定模式实现的最佳配置吗?
上述设置正在运行,但我正在寻求更多地了解为什么我应该使用我所做的范围。 (即 Transient 是我的 UOW 类(class)的最佳选择吗?为什么在这种情况下它比 Singleton 更好?等等)
最佳答案
通常我的经验法则是:
Scoped - 是可行的方法,可以节省缓存和您的头发,因为状态是为整个请求共享的。没有并发问题(所有作用域服务共享一个线程)。如果类在单个请求中多次使用,则不会创建实例。如果我不知道应该如何注册类(class),我会选择 scoped。通常,您在单个请求中多次需要一些东西 - 您可以计算一次,并在字段中设置值,因此下一次对客户的 CreditLimit 的查询将不会访问数据存储。
单例适用于缓存(服务器范围)、配置类、设计时考虑了多线程(多个请求)的对象。请注意,单例不应依赖于作用域对象。还要注意在多个线程中调用单例。如果您需要单例对请求数据执行某些操作,请将其作为函数参数传递。
临时注册在我的应用程序中很少见。我将它用于具有内部状态的类,它们可以多次使用,并且不应共享该状态。通常是实用程序或框架类。
示例作用域类? SqlConnection - 您不想从单个请求打开到数据库的多个连接(因为它由连接池处理)。还使用该连接的服务(服务只做一件事,因此不需要多个实例)。 Asp Controller 。
示例单例?今天浏览最多的文章。邮政编码验证器(没有依赖关系,虽然可以是单例)。
transient 示例?想一想如果该请求中的所有列表共享状态会发生什么。列表不是服务请求,而是您的代码,并且可以在单个请求期间用于不同目的。
请记住,如果单例具有 transient 或作用域依赖性,它将不会被释放,直到单例被释放(应用程序回收)。因此,范围内的事物可以依赖于单例,但单例不能依赖于范围。
说到 CQRS 和 DbContext - 在我的应用程序中,我只有一个 DbContext,由命令和查询共享。一切都在每个生命周期范围内注册(命令或查询在完成后不会保留状态,因此可以重复使用。将其设置为 transient 也可以)。 另一个例子是为 html 元素生成唯一 id 的类。它被注册为作用域,并在每次查询新 id 时递增内部计数器。如果类是 transient 的,当被下一个类调用时它会丢失它的状态。
请注意,有些人有其他观点。如果您使用多个生命周期范围,则最好转换为 transient 依赖项。如果我需要多次使用单个依赖项,我喜欢传递工厂,并且我尝试在我的应用程序中只有一个生命周期范围。
关于c# - .NET Core/EF 6 - 依赖注入(inject)范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37172161/
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时