【问题标题】:Multi-Tenant One Database One Schema ASP.NET MVC 5, Entity Framework 6,多租户一数据库一架构 ASP.NET MVC 5、实体框架 6、
【发布时间】:2015-05-28 14:43:07
【问题描述】:

我正在尝试为应用程序的多租户设置找到最佳方式。我想为客户提供一个数据库,每个表上都有一个 TenantId,其中一个表包含所有租户信息。 前任。 Db 租户表(TenantId、代码、名称等)

我的所有 WebApi 控制器和 MVC 控制器(WebApiBaseController 和 AppBaseController)都有一个基本控制器。我希望这两个控制器根据当前用户tenantId 归档结果。

应该由 DbContext 来处理这个问题吗?我确实想要一个 users.Where(u => u.TenantId == CurrenctUser.TenantId) 无处不在。

我也看过this question,但我认为这是他试图解决的另一个问题。

对于这个项目,我正在使用: ASP.NET MVC 5 WebAPI 2 实体框架 6 AspNet.Identity

如何根据当前登录的用户在单个位置使用其tenantId 过滤实体?

更新

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = false;
        Database.SetInitializer<ApplicationDbContext>(null);            
    }

    public DbSet<Tenant> Tenants { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    { 
        modelBuilder.Configurations.Add(new TenantMap());
        modelBuilder.Configurations.Add(new ApplicationUserMap());

        // Create parameterized filter for all entities that match type ITenantEntity                
        modelBuilder.Filter(Infrastructure.Constants.TetantFilterName, (ITenantEntity b) => b.TenantId, () => string.Empty);

        // By default the filter is disable to allow unauthenticated users to login
        // FIX: This filter must be Enabled at the base controller for mvc and webapi
        // basically, it will only get activated after the user logs in. See Base Controllers
        modelBuilder.DisableFilterGlobally(Infrastructure.Constants.TetantFilterName);
        base.OnModelCreating(modelBuilder);
    }

    public void EnableTenantFilter()
    {
        this.EnableFilter(Infrastructure.Constants.TetantFilterName);             
    }

    public void DisableTenantFilter()
    {
        this.DisableFilter(Infrastructure.Constants.TetantFilterName);
    }

}

 [Authorize]   
public class WebApiBaseController : ApiController
{

    ApplicationUser _currectUser;

    public  ApplicationUser CurrentUser
    {
        get
        {
            if (_currectUser == null)
            {
                AppDb.DisableTenantFilter();
                string currentUserId = User.Identity.GetUserId();
                _currectUser = AppDb.Users.FirstOrDefault(a => a.Id == currentUserId);

                AppDb.EnableTenantFilter();
            }


            return _currectUser;

        }
        set { _currectUser = value; }
    }

    public ApplicationDbContext AppDb
    {
        get;
        private set;
    }

    public WebApiBaseController(ApplicationDbContext context)
    {
        AppDb = context;

        if (User.Identity.IsAuthenticated)
        {    
            AppDb.SetFilterGlobalParameterValue(Infrastructure.Constants.TetantFilterName, CurrentUser.TenantId); 
        }            
    }

}

【问题讨论】:

  • 通过拦截添加过滤器可能是您最好的选择:lostechies.com/jimmybogard/2014/05/29/…
  • 我之前尝试过,但是当用户未通过身份验证时我遇到了问题。它无法找到用户,因为我必须在创建过滤器时定义一个空租户。到目前为止,这就是我所拥有的。请参阅问题更新
  • 如果你不知道租户是谁,因为你不知道用户是谁,你如何查询未知租户的数据?而且,最重要的是,为什么?
  • 使用github.com/jcachat/EntityFramework.DynamicFilters 时,您需要定义过滤器。如果用户尚未登录,我需要允许该用户进行身份验证。但是,我的 ApplicationDbContext 被空租户过滤,因此在登录期间找不到用户。请参阅更新以获取有效的解决方案。我知道这不是解决这个问题的最佳方法。
  • 如果每个租户都有自己的数据库架构,多租户会更容易(也更安全)。您可以在 EF 中轻松映射表 + 架构。

标签: asp.net-mvc entity-framework asp.net-web-api2 multi-tenant asp.net-identity-2


【解决方案1】:

恕我直言,我将用户上下文(租户 ID、用户 ID)发送到数据访问,并将租户 ID 设置为每个查询的过滤列,这确保了我的正确数据访问。

如果您选择基于控制器的过滤,如果您稍后需要一个 rest api 怎么办。在服务和/DAL 中处理安全系统是我认为最好的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-24
    • 2015-05-31
    • 1970-01-01
    相关资源
    最近更新 更多