【发布时间】:2018-08-20 21:03:58
【问题描述】:
请原谅我的无知,但似乎 MassTransit 有效地对待单例和作用域依赖项相同。至少在实体框架 DbContext 的情况下,因此,UserManager 通过扩展方法 AddEntityFrameworkStores 注册。
这意味着任何加载了跟踪或以其他方式添加到上下文的实体都会在应用程序生命周期内缓存。反过来,这意味着在服务被回收之前,无法识别通过上下文之外的任何内容(例如临时脚本)对这些实体所做的更改。
是否有解决此限制的最佳做法?对于上下文,请考虑启动时的以下 sn-p:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddDbContextPool<SomeDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("SomeConnectionString")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<SomeDbContext>()
.AddDefaultTokenProviders();
// ...
}
还有以下消费者:
public class SomeConsumer : IConsumer<ISomeRequest>
{
private readonly SomeDbContext _dbContext;
private readonly UserManager<IdentityUser> _userManager;
public SomeConsumer(SomeDbContext dbContext, UserManager<IdentityUser> userManager)
{
_dbContext = dbContext;
_userManager = userManager;
}
public async Task Consume(ConsumeContext<ISomeRequest> context)
{
var identityUser1 = await _dbContext.Users.FindAsync(1);
var identityUser2 = await _userManager.FindByIdAsync(1);
var consumerHashCode = GetHashCode();
var dbContextHashCode = _dbContext.GetHashCode();
var userManagerHashCode = _userManager.GetHashCode();
var identityUser1HashCode = identityUser1.GetHashCode();
var identityUser2HashCode = identityUser2.GetHashCode();
context.Respond(new SomeResponse());
}
}
在上面的示例中,消费者(注册的瞬态)为每个请求提供不同的哈希码。尽管数据库上下文和用户管理器被注册为作用域,但所有其他人都提供相同的服务(建议相同的实例)。
万一重要的是,MassTransit 是从控制台应用程序而不是 Web 应用程序运行的。
【问题讨论】:
-
您是否使用 MS DI 扩展库来支持对每条消息进行范围界定? nuget.org/packages/MassTransit.Extensions.DependencyInjection/…
-
我现在不在。我开始沿着这条路走下去,但这只会让情况变得更糟。那时,事件瞬变开始提供相同的哈希码。这个扩展是专门用来启用范围支持的吗?我会给它一个更深入的镜头,看看它是否能解决我的问题。
-
您必须使用该程序集中的消费者工厂在您的容器中为您的作用域实例创建一个嵌套作用域。
标签: dependency-injection .net-core rabbitmq entity-framework-core masstransit