セッションごとに個別のクエリプランキャッシュを使用できますか?


質問

私はマルチテナントのASP.NETアプリケーションを持っており、データベースにはソフト削除が設定されています。最初は、クエリレベルで直接データの制限を処理しました。たとえば、次のようになります。

var foos = context.Foos.Where(foo => !foo.Deleted && foo.TenantId = currentTenantId).ToList();

ご想像のように、これはデータアクセスレイヤーのすべてのクエリを膨らませ、正しいフィルタ条件を追加することを忘れると、APIを非常に脆弱にします。 Z.EntityFramework.Plus.EF6使用して、グローバルフィルタリングをコンテキストに適用することを決定しZ.EntityFramework.Plus.EF6

var foos = context.Foos.Where(foo => !foo.Deleted && foo.TenantId = currentTenantId).ToList();

これは、1人のユーザーにとって完全に機能します。ただし、テナントを切り替えると、フィルタ式がクエリプランキャッシュに保存されるという問題が発生します 。これはEntity Framework Plusの既知の問題です。解決されていないため、回避策を見つける必要があります。

私が考えることができる最も即座の解決策は、クエリプランキャッシュの存続期間を現在のセッションに関連付けることです。ユーザーがログアウトするかテナントを切り替えると、キャッシュは破棄されます。これは可能ですか?もしそうなら、私はこれをどのように達成できますか?

受け入れられた回答

私はまったく同じ問題を抱えていて、同じ問題でZ.EntityFramework.Plus.EF6を使って作業しようとしました。 zzzprojectsチームにもEntityFramework.DynamicFiltersがあり、この目的のためにはるかに優れています。キャッシュされたクエリはパラメータ化され、値は実行時に指定したセレクタ関数を使用して注入されます。

using System.Data.Entity;
using EntityFramework.DynamicFilters;

public class Program
{   
    public class CustomContext : DbContext
    {
        private int _tenantId;

        public int GetTenantId()
        {
            return _tenantId;
        }

        // Call this function to set the tenant once authentication is complete.
        // Alternatively, you could pass tenantId in when constructing CustomContext if you already know it
        // or pass in a function that returns the tenant to the constructor and call it here.
        public void SetTenantId(int tenantId)
        {
            _tenantId = tenantId;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Filter applies to any model that implements ITenantRestrictedObject
            modelBuilder.Filter(
                "TenantFilter",
                (ITenantRestrictedObject t, int tenantId) => t.TenantId == tenantId,
                (CustomContext ctx) => ctx.GetTenantId(), // Might could replace this with a property accessor... I haven't tried it
                opt => opt.ApplyToChildProperties(false)
            );
        }
    }

    public interface ITenantRestrictedObject
    {
        int TenantId { get; }
    }
}




ライセンスを受けた: CC-BY-SA
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ