1

I would like to ask your opinions regarding the way I handle MultiTenancy. I"m using MVC3 (switching to MVC4) and EF as my backend. I'm using a single app, shared schema MultiTenancy. Below is the code:

public abstract class Service<T> where T : Entity
{
    private Repository<T> _repo;
    public Service()
    {
        _repo = new Repository<T>();
    }

    public bool Authenticate(int id)
    {
        //var companyInfo = _authorizationRepository.GetApiKey(apiKey);
        int tenantId = 0; // replaced by companyInfo using repository
        var entity = _repo.GetQuery(tenantId).Where(e => e.Id == id).First();

        if (tenantId != entity.TenantId)
            throw new ArgumentException();

        return true;
    }
}

public class EmployeeService : Service<Employee>
{
    private EmployeeRepository employeeRepository;
    public EmployeeService()
    {
        employeeRepository = new EmployeeRepository();
    }

    public Employee GetEmployeeById(int employeeId)
    {
        this.Authenticate(employeeId);
        return employeeRepository.GetById(employeeId);
    }
}

public class Entity
{
    public int Id { get; set; }
    public int TenantId { get; set; }
}

Of course DI will be there as well but for simplicity I removed them here (temporarily). I used Generics (feeling dirty about it) on the Service Layer since I'm having trouble on comparing the TenantId with the correct Entity that will be passed on the class. I'm eyeing to recode this using FilterAttributes but I dont have any idea how to. How do you guys handle your multitenancy? Is the design have some crucial flaws that I may encounter on the long run? If you have some samples using FilterAttributes that would be a big help.

Thanks!

4

1 に答える 1

2

現在、かなり大きなマルチテナンシー Web アプリを構築しています。見た目ほど単純ではありませんが、アーキテクチャを構築すれば後は簡単です。私たちは開発に深く取り組んでいますが、nanocms.codeplex.com でオープン ソースの部分を確認できます (数日以内に db jet butt をアップロードしていません)。

これはかなり広い質問なので、いくつかの問題と解決策を要約しようと思います。

まず、リクエストごとにテナントを識別する必要があります。URL を解析し、データベース内のデータと比較するグローバル アクション フィルターがあります。もちろん、データベースへの呼び出しが行われないように、すべてのデータをキャッシュする必要があります。ユーザーは一度に複数のテナントにアクセスできるため、それらを Cookie またはセッションに保存しないでください。そのデータを HttpRequest アイテムに入れることをお勧めします。これにより、リクエストで 1 回だけ行うことができますが、そのデータは常に利用可能です。

認証の場合、ユーザーは一意である必要があります。一部のユーザーにテナントごとに異なる権限を付与するかどうかを検討する必要があります。その場合は、現在のテナントでの役割を確認できるように、認証コードと属性を記述する必要があります。私たちのアプリでは、ユーザーが認証するときにセッション オブジェクトを作成します。オブジェクトには、テナントの権限をチェックする静的メソッドがあります。

HttpRequest アイテムを強く型付けしておくことをお勧めします。我々は持っています:

public static int TenantID {
    get { return System.Web.HttpContext.Current.Items.Contains("TenantID") ? Convert.ToInt32(System.Web.HttpContext.Current.Items["TenantID"]) : -1; }
    set {
        if (!System.Web.HttpContext.Current.Items.Contains("TenantID"))
            System.Web.HttpContext.Current.Items.Add("TenantID", value);
        System.Web.HttpContext.Current.Items["TenantID"] = value;
    }
}
于 2012-04-17T15:27:06.863 に答える