5

マルチテナント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);

私の場合はどうしますか?必要に応じて、アーキテクチャを再検討したいと思います。

ありがとう、ニコラ

4

1 に答える 1

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);
}
于 2012-07-10T11:55:31.810 に答える