- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我关注了一篇博文“使用 ASP.NET Core 和 Visual Studio Code 构建您的第一个 Web API”。
http://www.codingflow.net/building-your-first-web-api-with-asp-net-core-and-visual-studio-code/
在这种情况下,数据不会保存在数据库中,而是像这样保存在内存中:
services.AddDbContext<TodoContext>(options => options.UseInMemoryDatabase());
services.AddSingleton<ITodoRepository, TodoRepository>();
你会注意到:
(1) UseInMemoryDatabase
在 DbContext
上
(2) TodoRepository
上的AddSingleton
这很好用。现在,我更新了代码以将数据保存在真实数据库 中。所以主要的变化是:
services.AddDbContext<TodoContext> (options => options.UseSqlite("Data Source=blogging.db"));
services.AddSingleton<ITodoRepository, TodoRepository>();
我想通知我必须将 AspNetCore
从 1.0 迁移到 2.2。
现在在运行时,当以 Controller 为目标时,我收到错误:无法使用来自单例“Models.ITodoRepository”的作用域服务“Models.TodoContext”。
我理解在这种情况下:
我的 TodoContext
是一个 Scoped 对象:在一个请求中相同,但在不同请求之间不同。
我的 TodoRepository
是一个单例对象:每个对象和每个请求都相同。
所以我最终将 AddSingleton
更改为 AddScoped
,效果非常好:
services.AddDbContext<TodoContext> (options => options.UseSqlite("Data Source=blogging.db"));
services.AddScoped<ITodoRepository, TodoRepository>();
我的问题是:要知道这是否是一种可接受的方法?
PS:我知道在 SO 上还有关于此问题的其他问题,但我没有阅读明确的回复。
最佳答案
ASP.NET Core 内置的依赖注入(inject)容器保护您免受称为“俘虏依赖”的依赖注入(inject)反模式(您可以阅读更多关于它和一般依赖注入(inject)的信息 here )。
基本思想是,具有特定生命周期的类只能依赖于生命周期等于或长于自身生命周期的对象。这是因为当你进行依赖注入(inject)时,你提供了一个类及其所有依赖项(通常通过构造函数注入(inject)),并且该类保存了对依赖项的引用,以便以后需要时可以使用它。
因为您正在设计的类保存了对注入(inject)对象的引用,所以只要您的类的实例存在,注入(inject)对象就会(至少)保持事件状态。也许一个例子可以帮助你理解。
public interface IFoo {}
public class Foo: IFoo {}
public class Bar
{
private readonly IFoo foo;
public Bar(IFoo foo)
{
this.foo = foo ?? throw new ArgumentNullException(nameof(foo));
}
}
var foo = new Foo();
var bar = new Bar(foo); // the object referenced by foo variable is alive as long as the Bar instance is alive, because a reference to it is saved inside the private field of Bar instance
如果 Foo 实例的预期生命周期短于 Bar 实例的预期生命周期,这种情况可能会给您带来麻烦。
例如,假设在 Web 应用程序的上下文中,假设类 Foo 不是线程安全的,因此从不同线程同时访问它的实例可能会导致其私有(private)状态损坏。在这种情况下,您可以决定将 Foo 类注册为作用域依赖项,这样每次应用程序收到 HTTP 请求时,都会创建一个新的 Foo 实例,并且该实例将在 HTTP 请求的整个生命周期内重复使用。这样做很好,即使处理 HTTP 请求意味着使用一些异步操作。假设您在每个涉及的异步操作上等待,最多只能有一个线程同时访问您的 Foo 实例,并且实例的内部状态被保存以防止损坏。
在这种情况下,如果您将 Bar 类注册为单例,那么在应用程序的整个生命周期中可能只有一个 Bar 实例,因此不同的线程将同时访问 Bar 实例(请记住,Web 应用程序能够通过使用线程池同时处理多个请求)。您的 Bar 单例实例引用了 Foo 的实例,该实例可能会被多个线程并发使用,这将导致其内部状态损坏并导致不可预测的结果。你有一个俘虏依赖,因为你有一个单例( Bar 类),它依赖于一个生命周期较短的类(作用域 Foo 类)。
回到你的问题,你的解决方案很好:你不能将你的存储库注册为单例,因为它必须使用作用域依赖项,所以在我看来将它注册为作用域服务是很好的方法。
关于c# - 无法使用单例 yyy 的作用域服务 xxx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55325828/
我正在尝试在我的应用程序中使用 WCF 4.0 服务。我从头开始构建、测试和部署服务。该服务在 WCF 测试客户端中工作,并且可以在我构建的任何其他测试项目中使用。问题是这个特定的应用程序……唯一重要
标题已经说出了我想问的一切。我无法理解使用 window 和 const {} 的主要区别是什么。 我都试过了,结果是一样的。你能帮我理解这一点吗? 附注我正在使用 Laravel,它使用 windo
我想匹配下面的字符串, str1: xxx(yyy) (zzz(qqq)) str2: xxx(yyy) 我写了一个正则表达式,只能匹配str1: >>> s = re.compile(r'([^\(
我该如何拆分 list = ['a', 'xxx yyy zzz'] 进入 list = ['a', 'xxx', 'yyy', 'zzz'] 在 Python 2.7.5+ 中(默认,2013 年
是否有一种内置的简单方法可以将字符串转换为整数,字符串格式为 xxx,yyy,zzz?喜欢 325,121,565 而不是 325121565。我知道我可以构建一个函数来执行此操作,但我想知道是否其他
在调试大型项目时,我使用日志打印输出中的链接直接跳转到相关文件和行。唉,在很多情况下我都会收到以下弹出窗口: XXX is not a valid line number in YYY.java 在主
我在从服务调用方法时遇到问题。该错误仅发生在 .NET 中,Java 似乎工作正常。该服务中的大多数方法都适用于 .NET,到目前为止,其中 2 个方法已引发异常。如果您想尝试重现,该服务已开放:ht
Eclipse 向我报告了一个问题: The project XXX does not have any GWT SDKs on its build path ...我很难弄清楚这个问题是从哪里来的以
编译文件error_xxx_does_not_name_a_type.cpp ,为什么会出现错误 error_xxx_does_not_name_a_type.cpp:5:28: error: ‘A’
我升级到 xcode 4.0,现在在编译时遇到这个错误: “在‘yyy’类型的对象上找不到属性‘xxx’” 其中 xxx 是属性,yyy 是我的代表。 我正在尝试按如下方式在委托(delegate)对
我关注了一篇博文“使用 ASP.NET Core 和 Visual Studio Code 构建您的第一个 Web API”。 http://www.codingflow.net/building-y
有人告诉我这是对我最后一个 question 的回答那个 char *name[] = {"xxx", "yyy"} 被编译器更改为 char *name[] = {Some_Pointer, Som
我有两个 android 项目,ProjA 需要 ProjB(在 Eclipse 属性 > Java 构建路径 > 项目 > 添加 > ProjB)。在 Eclipse 中一切都可以编译,但是当我运行
我安装了bind在 CentOS 6 服务器上配置 DNS 区域以定义域。我的 /etc/named.conf这是: options { # listen-on port 53 { 1
这个问题在这里已经有了答案: Unable to resolve service for type while attempting to activate (10 个答案) 关闭 2 年前。 我有
我得到的原始数据是这样的,都在一列 John;Peter;Eric; Susan;Mary;Kate; 但我想将它们分成三个单独的列 John Peter Eric Susan Mary Ka
Jenkins 在完成测试执行后给出以下内容: Error sending to the following INVALID addresses: valid emailid Jenkins 构建日志
我想编写一个 servlet 或过滤器,自动将 url/xxx/yyy/zzz 映射到类 XxxYyyZzz.java。 例如,以下 URL 将映射到以下 java 类: /comment/add -
我遇到了这个错误: error: failed to parse manifest at `...\Cargo.toml` Caused by: Feature `client` depends
我试图通过获取日期然后填充表来获取存储在数据库中的数据。 List contents = new ArrayList<>(); List records try { S
我是一名优秀的程序员,十分优秀!