多租户实体过滤

时间:2013-12-16 09:54:25

标签: c# entity-framework entity-framework-6

我正在开发多租户应用程序,其中不同的公司在CompanyID列之间有所不同。数据库中还有一些共同的核心表,如Settings,所有公司都是一样的。我有两个基本持久类:PersistentObjectCompanyPersistentObject。最后一个继承自第一个并添加CompanyId属性。我将直接在存储库中插入公司ID标准,如下所示:

public class EntityFrameworkRepository<T> : Repository<T>
    where T : PersistentObject
{
    private readonly DbSet<T> set;
    private readonly IApplicationContext applicationContext;
    private readonly IQueryable<T> queryable;

    public EntityFrameworkRepository(DbSet<T> set,
                                     IApplicationContext applicationContext)
    {
        this.set = set;
        this.applicationContext = applicationContext;

        if (typeof (CompanyPersistentObject).IsAssignableFrom(typeof(T)))
        {
            // TODO: Apply CompanyPersistentObject filter
            // using applicationContext.CompanyID
        }
    }
}

这是一种好方法,还是可以提出更好的解决方案? 如果是这样,如何在CompanyPersistentObject DbSet<T> T PersistentObject并且没有CompanyId属性的情况下注入{{1}}的条件?

2 个答案:

答案 0 :(得分:1)

我几乎完全按照你的申请提出的建议。我发现最棘手的方法是“All”包装器。我想返回IQueryable但是linq到实体不支持转换为实体。这个问题的答案在这里提供:

How to conditionally filter IQueryable by type using generic repository pattern

我确实开始使用Martin Eden建议的技术,但我将其重新考虑到您建议的单个基础存储库中,现在它变得更加简单和安全。

这就是我的“查找”方法:

    public virtual T Find(int id)
    {
        T e = Context.Set<T>().Find(id);

        var od = e as OrganisationDependent;
        if (od != null && od.OrganisationID != CurrentOrganisationID)
            return null;

        if (e == null)
            return null;

        return e;
    }

答案 1 :(得分:0)

我建议您使用具有此行为的CompanyRepository类扩展EntityFrameworkRepository类。然后,您可以将CompanyRepository的类型参数限制为仅扩展CompanyPersistentObject(或更好的接口)的类。

例如:

public class EntityFrameworkRepository<T> : Repository<T>
    where T : PersistentObject
{
    private readonly DbSet<T> set;
    private readonly IApplicationContext applicationContext;
    private readonly IQueryable<T> queryable;

    public EntityFrameworkRepository(DbSet<T> set,
                                 IApplicationContext applicationContext)
    {
        this.set = set;
        this.applicationContext = applicationContext;
    }
}


public class CompanyRepository<T> : Repository<T>
    where T : PersistentObject, ICompany
{
    public CompanyRepository(DbSet<T> set,
                                 IApplicationContext applicationContext)
    {
        this.set = setFilteredById(set, applicationContext.CompanyId);    
    }
}