I'm developing a multi-tenant web app (stack: MVC 4 + Entity framework 4.3). My requirements are pretty simple: each tenant has the same UI and CodeBase.
In my database I have some tables with a TenantId field (and other tables without).
I have set up a very simple generic repository:
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;
}
I'd like the "get" methods to filter for my tenantId. My insert, update and delete method should also constrain the appropriete TenantId.
My Entities are autogenerated POCO classes.
I have considered these solutions:
1- GenericRepository should implement a "ITenant" interface that defines TenantId. Problem is that some entities haven't got the TenantId property. Also, I don't really like to modify the T4 template I use to generate POCO objects to make them implement my interface
2- Reflection (but of course EF can't translate it to a SQL statement)
if (typeof(TEntity).GetProperty("TenantId") != null)
query = query.Where(x => (int) (x.GetType().GetProperty("TenantId").GetValue(x, null)) == tenantId);
What would you do in my case? I'm willing to reconsider my architecture if necessary.
Thanks, Nicola
You can do the reflection check and then manually create an expression tree that EF can understand.
For example:
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With