全域查詢篩選器Global Query Filters

全域查詢篩選器是 LINQ 查詢述詞 (布林值運算式通常傳遞至 LINQ其中查詢運算子) 套用至實體類型的中繼資料模型中 (通常在OnModelCreating)。Global query filters are LINQ query predicates (a boolean expression typically passed to the LINQ Where query operator) applied to Entity Types in the metadata model (usually in OnModelCreating). 這類篩選器會自動套用至涉及這些實體類型,包括實體類型的直接或間接,例如透過使用包含參考導覽屬性參考任何 LINQ 查詢。Such filters are automatically applied to any LINQ queries involving those Entity Types, including Entity Types referenced indirectly, such as through the use of Include or direct navigation property references. 這項功能的一些常見的應用程式如下:Some common applications of this feature are:

  • 虛刪除-實體類型定義IsDeleted屬性。Soft delete - An Entity Type defines an IsDeleted property.
  • 多租用戶-實體類型定義TenantId屬性。Multi-tenancy - An Entity Type defines a TenantId property.

範例Example

下列範例會示範如何使用全域查詢篩選器來實作簡單的部落格模型中的虛刪除和多租用戶的查詢行為。The following example shows how to use Global Query Filters to implement soft-delete and multi-tenancy query behaviors in a simple blogging model.

提示

您可以檢視這篇文章範例GitHub 上。You can view this article's sample on GitHub.

首先,定義實體:First, define the entities:

public class Blog
{
    private string _tenantId;

    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public bool IsDeleted { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

請注意 宣告_tenantId_欄位_部落格_實體。Note the declaration of a __tenantId field on the Blog entity. 這會用來將每個部落格執行個體與特定租用戶產生關聯。This will be used to associate each Blog instance with a specific tenant. 也定義是_IsDeleted_屬性_Post_實體類型。Also defined is an IsDeleted property on the Post entity type. 這使用此選項以追蹤是否_Post_執行個體已 「 虛刪除 」。This is used this to keep track of whether a Post instance has been "soft-deleted". 也就是執行個體標示為已刪除 withouth 實際移除基礎資料。I.e. The instance is marked as deleted withouth physically removing the underlying data.

接下來,設定中的查詢篩選器_OnModelCreating_使用HasQueryFilter應用程式開發介面。Next, configure the query filters in OnModelCreating using the HasQueryFilter API.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property<string>("TenantId").HasField("_tenantId");

    // Configure entity filters
    modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<string>(b, "TenantId") == _tenantId);
    modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);
}

述詞運算式傳遞至_HasQueryFilter_呼叫,現在將會自動套用至任何 LINQ 查詢,針對這些型別。The predicate expressions passed to the HasQueryFilter calls will now automatically be applied to any LINQ queries for those types.

提示

請注意使用 DbContext 執行個體層級欄位:_tenantId用來設定目前的租用戶。Note the use of a DbContext instance level field: _tenantId used to set the current tenant. 模型層級篩選器會使用正確的內容執行個體的值。Model-level filters will use the value from the correct context instance. 也就是正在執行查詢的執行個體。I.e. The instance that is executing the query.

停用篩選器Disabling Filters

篩選器可能會停用個別的 LINQ 查詢使用IgnoreQueryFilters()運算子。Filters may be disabled for individual LINQ queries by using the IgnoreQueryFilters() operator.

blogs = db.Blogs
    .Include(b => b.Posts)
    .IgnoreQueryFilters()
    .ToList();

限制Limitations

全域查詢篩選器有下列限制:Global query filters have the following limitations:

  • 篩選條件不能包含參考導覽屬性。Filters cannot contain references to navigation properties.
  • 只可以定義篩選,根實體類型的繼承階層架構。Filters can only be defined for the root Entity Type of an inheritance hierarchy.