具有实体框架的简单多租户Web应用程序的解决方案

时间:2012-07-10 11:45:13

标签: entity-framework multi-tenant

我正在开发一个多租户Web应用程序(堆栈:MVC 4 + Entity framework 4.3)。 我的要求非常简单:每个租户都有相同的UI和CodeBase。

在我的数据库中,我有一些带有TenantId字段的表(以及没有其他表的表)。

我已经建立了一个非常简单的通用存储库:

public class GenericRepository<TEntity> where TEntity : class
{
    internal Database.CRMEntities context;
    internal DbSet<TEntity> dbSet;
    internal int tenantId;

    public GenericRepository(Database.CRMEntities context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
        this.tenantId = 1;
    }

我想要“get”方法来过滤我的tenantId。我的插入,更新和删除方法也应该约束适当的TenantId。

我的实体是自动生成的POCO课程。

我考虑过这些解决方案:

1- GenericRepository应该实现一个定义TenantId的“ITenant”接口。问题是某些实体没有获得TenantId属性。另外,我真的不想修改我用来生成POCO对象的T4模板,以使它们实现我的界面

2-反射(但当然EF不能将其转换为SQL语句)

if (typeof(TEntity).GetProperty("TenantId") != null)
            query = query.Where(x => (int)   (x.GetType().GetProperty("TenantId").GetValue(x, null)) == tenantId);

在我的情况下你会做什么?如有必要,我愿意重新考虑我的架构。

谢谢, 尼古拉

1 个答案:

答案 0 :(得分:5)

您可以进行反射检查,然后手动创建EF可以理解的表达式树。

例如:

int tenantId = 5;

var tenantIdInfo = typeof(TEntity).GetProperty("TenantId");

if (tenantIdInfo != null)
{
    var entity = Expression.Parameter(typeof(TEntity), "it");

    var predicate = (Expression<Func<TEntity, bool>>)Expression.Lambda(
        Expression.Equal(
            Expression.MakeMemberAccess(entity, tenantIdInfo),
            Expression.Constant(tenantId, typeof(int))),
        entity);

    query = query.Where(predicate);
}