Dependency Injection을 사용하여 Repository 생성자에게 UserId / TenantId를 전달하는 방법?

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

문제

ASP.NET 5와 EF7을 사용하여 멀티 테넌트 웹 서비스를 작성하고 있습니다. 저장소 데이터는 임차인 / 사용자에게 한정됩니다. 모든 호출에서 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와 사용자 ID 값은 모두 런타임 데이터이므로 시스템의 구성 요소 (이 경우 저장소)에 런타임 데이터를 삽입 하면 안됩니다. 이는 사용자가 이미 경험 한대로 구성 루트를 엄청나게 복잡하게 만들고 거의 불가능하게 만들기 때문에 개체 그래프를 확인합니다. 런타임 데이터는 이미 생성 된 객체 그래프를 통과해야합니다. 이것을 달성하는 기본적으로 두 가지 방법이 있습니다. 구성 요소의 공용 API 메소드 호출을 통해 데이터를 전달하거나 요청시 런타임 값을 검색하는 구성 요소를 주입하십시오.

귀하의 경우, 후자의 옵션이 가장 좋습니다. 그러므로 나의 조언은이 문맥 정보를 검색 할 수있는 컴포넌트를 삽입하는 것이다.

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();
}

이렇게하면 현재 요청에 대한 올바른 임차인 ID를 검색하는 방법을 알고있는 ITenantContext 구현을 정의 할 수 있기 때문에 문제를 우아하게 해결할 수 있습니다. 예를 들면 :

public sealed class AspNetSessionTenantContext : ITenantContext {
    public int CurrentTenantId {
        get { return (int)HttpContext.Current.Session["tenantId"]; }
    }
}

이렇게하면 모든 구성 요소를 싱글 톤으로 등록 할 수 있으므로 성능을 향상시키고 Captive Dependencies 와 같은 일반적인 DI 함정의 변경을 줄일 수 있습니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.