1

我想就我处理 MultiTenancy 的方式询问您的意见。我正在使用 MVC3(切换到 MVC4)和 EF 作为我的后端。我正在使用单个应用程序,共享模式 MultiTenancy。下面是代码:

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

当然 DI 也会在那里,但为了简单起见,我在这里(暂时)删除了它们。我在服务层上使用了泛型(感觉很脏),因为我无法将 TenantId 与将在类上传递的正确实体进行比较。我正在考虑使用 FilterAttributes 重新编码,但我不知道该怎么做。你们是如何处理多租户的?从长远来看,设计是否存在一些我可能会遇到的关键缺陷?如果您有一些使用 FilterAttributes 的示例,那将是一个很大的帮助。

谢谢!

4

1 回答 1

2

我们目前正在构建相当大的多租户网络应用程序。嗯,它并不像看起来那么简单,但是一旦你构建了你的架构,它就很简单了。我们正在深入开发,但您可以查看 nanocms.codeplex.com 中的开源部分(我们还没有上传 db jet butt,我们将在几天内上传)

由于这是一个相当广泛的问题,我将尝试总结一些问题和解决方案。

首先,您需要为每个请求识别租户。我们有一个全局操作过滤器,它解析 url 并将其与数据库中的数据进行比较。当然,您必须缓存所有数据,这样就不会调用数据库。您不得将任何内容保存在 cookie 或会话中,因为用户一次可以访问多个租户。我建议您将该数据放在 HttpRequest Items 中,以便您在请求中只执行一次,但始终可以使用该数据。

对于身份验证用户必须是唯一的。您必须考虑是否要授予某些用户对每个租户的不同权限。如果是这样,您必须编写您的身份验证代码甚至属性,以便您可以检查他在当前租户中的角色。在我们的应用程序中,当用户进行身份验证时,我们会创建会话对象。在对象中,我们有检查租户权限的静态方法。

我建议你保持 HttpRequest Items 的强类型。我们有:

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 回答