asp.net-mvc - 如何使用依赖注入(inject)将 UserId/TenantId 传递给存储库构造函数?

标签 asp.net-mvc dependency-injection asp.net-core asp.net-core-mvc entity-framework-core

我正在使用 ASP.NET 5 和 EF7 编写 Multi-Tenancy Web 服务。存储库数据特定于租户/用户。因为我将在所有调用中使用 TenantId,所以我想用当前的 TenantId 初始化存储库。

public class MyRepository {
    private int tenantId;
    public MyRepository(MyDbContext context, int tenantId) { 
        this.tenantId = tenantId;
        // ...
    }

    public Task<List<Data>> GetAllAsync() {
        return this.context.Data.Where(d => d.TenantId == this.tenantId).ToListAsync();
    }
}

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        // How do I pass the TenantId to the constructor?
        services.AddScoped<MyRepository>();
    }
}

用户通过身份验证后是否可以初始化我的存储库一次?我将如何通过构造函数传递 TenantId?

最佳答案

您的租户和用户 ID 值都是运行时数据,您应该 not inject runtime data into the components of your system (在这种情况下是您的存储库),因为这会使您的组合根非常复杂(正如您已经经历的那样)并且几乎不可能验证您的对象图。运行时数据应流经已构建的对象图。基本上有两种方法可以实现这一点。要么通过组件的公共(public) API 的方法调用传递数据,要么注入(inject)一个组件,该组件负责在请求时检索运行时值。

在您的情况下,后一种选择是最好的。因此,我的建议是注入(inject)一个允许检索此上下文信息的组件:

public interface ITenantContext
{
    int CurrentTenantId { get; }
}

public interface IUserContext
{
    int CurrentUserId { get; }
}

public class MyRepository {
    private readonly Func<MyDbContext> contextProvider;
    private readonly ITenantContext tentantContext;

    public MyRepository(Func<MyDbContext> contextProvider, ITenantContext tentantContext){ 
        this.contextProvider = contextProvider;
        this.tentantContex = tentantContex;
    }

    public Task<List<Data>> GetAllAsync() {
        return this.contextProvider().Data
            .Where(d => d.TenantId == this.tenantContext.CurrentTenantId)
            .ToListAsync();
}

这优雅地解决了问题,因为现在您可以定义 ITenantContext知道如何为当前请求检索正确的租户 ID 的实现。例如:
public sealed class AspNetSessionTenantContext : ITenantContext {
    public int CurrentTenantId {
        get { return (int)HttpContext.Current.Session["tenantId"]; }
    }
}

这甚至允许您将所有组件注册为单例,这可以提高性能,并减少常见 DI 陷阱的变化,例如 Captive Dependencies .

关于asp.net-mvc - 如何使用依赖注入(inject)将 UserId/TenantId 传递给存储库构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32685571/

相关文章:

asp.net-mvc - Azure Web应用程序和Web api服务(移动服务)架构全局分布

c# - 在 Simple Injector 中注册具有原始配置依赖项的装饰器

java - 动态加载接口(interface)实现时如何使接口(interface)成为仅编译依赖项

asp.net-core - "No database provider has been configured for this DbContext"

asp.net-mvc - 相对于当前 Controller 的 MVC Ajax 操作

c# - 如何以格式 23 :59:59 转换日期时间

c# - Asp.Net Core 中的@Html.Action

powershell - 错误: Need to specify the physical directory for the virtual path 'Web/' of role

asp.net-mvc - 在 MVC4 上使用 HttpClient 进行异步调用

dependency-injection - 您最常使用哪种松散耦合模式?