【发布时间】: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