2012-07-10 32 views
5

我正在开发一个多租户Web应用程序(堆栈:MVC 4 +实体框架4.3)。 我的要求很简单:每个租户都有相同的UI和CodeBase。一个简单的多租户Web应用程序与实体框架的解决方案

在我的数据库中,我有一些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。我的插入,更新和删除方法也应该限制appantriete TenantId。

我的实体是自动生成的POCO类。

我已经考虑到了这些解决方案:

1- GenericRepository应实行 “ITenant” 接口定义TenantId。问题是有些实体没有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); 

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

感谢, 尼古拉

回答

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); 
} 
+0

谢谢你的答案。一个表达式应该可以工作......并且这是用于管理复杂问题的一段非常简单的代码。我想知道......是反射“慢”还是我可以使用它没有任何问题? – 2012-07-10 12:00:50

+0

反射确实会对性能产生相当大的影响,但您需要针对特定​​场景对其进行测量,以确定它是否可接受。 – 2012-07-10 13:09:37

+0

我跑了一些测试:选择查询重复1000次,只返回一行约慢5%。这不是一个完整的测试,但现在已经足够了。 如果没有人在几天内提出一个更好的主意,我会将我的问题标记为回答。 谢谢! – 2012-07-10 20:07:07

相关问题