EF Core:如何基于关联表设置Permission层级的鉴别器
基于EF Core鉴别器区分Permission模型的解决思路
方案一:TPH继承+查询过滤(EF层面类型约束)
通过为PermissionBase配置表每层级(TPH)继承,结合查询过滤,利用ProductBase的鉴别器值约束不同权限子类关联的产品类型。
- 调整实体结构
将权限类的导航属性统一指向抽象基类ProductBase,而非具体的Product或Addon:
public abstract class PermissionBase { public string ID { get; set; } // 补充主键字段 public string ProductID { get; set; } public virtual ProductBase Product { get; set; } } public class ProductPermission : PermissionBase { } public class AddonPermission : PermissionBase { }
- EF Core Fluent配置
- 为
PermissionBase设置TPH继承的鉴别器 - 为每个权限子类配置与
ProductBase的关联,并添加查询过滤,确保仅关联对应类型的产品:
// 配置PermissionBase的TPH继承 builder.Entity<PermissionBase>() .HasDiscriminator<string>("PermissionType") .HasValue<ProductPermission>("ProductPermission") .HasValue<AddonPermission>("AddonPermission"); // 配置ProductPermission与Product的关联及过滤 builder.Entity<ProductPermission>() .HasOne(p => p.Product) .WithMany() // 根据实际业务调整反向导航属性 .HasForeignKey(p => p.ProductID) .IsRequired(); // 过滤:仅允许关联Type为"Product"的产品 builder.Entity<ProductPermission>() .HasQueryFilter(p => p.Product.Type == "Product"); // 配置AddonPermission与Addon的关联及过滤 builder.Entity<AddonPermission>() .HasOne(p => p.Product) .WithMany() .HasForeignKey(p => p.ProductID) .IsRequired(); // 过滤:仅允许关联Type为"Addon"的产品 builder.Entity<AddonPermission>() .HasQueryFilter(p => p.Product.Type == "Addon");
方案二:TPT继承+数据库检查约束(强一致性保障)
如果需要数据库层面的强约束,可以采用表每类型(TPT)继承,同时为权限表添加检查约束,确保关联的产品类型匹配。
- EF Core配置TPT继承
builder.Entity<PermissionBase>().ToTable("Permissions"); builder.Entity<ProductPermission>().ToTable("ProductPermissions"); builder.Entity<AddonPermission>().ToTable("AddonPermissions");
- 添加数据库检查约束
手动执行SQL语句,为每个权限表添加检查约束:
-- 为ProductPermission表添加约束 ALTER TABLE ProductPermissions ADD CONSTRAINT CK_ProductPermission_ProductType CHECK (EXISTS (SELECT 1 FROM ProductBase WHERE ID = ProductID AND Type = 'Product')); -- 为AddonPermission表添加约束 ALTER TABLE AddonPermissions ADD CONSTRAINT CK_AddonPermission_AddonType CHECK (EXISTS (SELECT 1 FROM ProductBase WHERE ID = ProductID AND Type = 'Addon'));
方案三:整合权限到产品实体(简化结构)
如果业务允许,可以将权限集合直接作为ProductBase的属性,利用产品的鉴别器自动区分权限类型:
public abstract class ProductBase { public string ID { get; set; } public string Type { get; set; } public virtual ICollection<PermissionBase> Permissions { get; set; } }
这种方式无需单独处理权限类的类型区分,直接通过产品的鉴别器关联对应权限。
内容的提问来源于stack exchange,提问作者i_ll_be_back
相关产品推荐
相关产品推荐

