Entity framework 来自DbContext的Ef核心抽象HasQueryFilter
我正试图在DbContext上构建一些通用的authorize东西,这样我的开发人员就不需要关心repos/域中的授权 简单的例子如Entity framework 来自DbContext的Ef核心抽象HasQueryFilter,entity-framework,entity-framework-core,Entity Framework,Entity Framework Core,我正试图在DbContext上构建一些通用的authorize东西,这样我的开发人员就不需要关心repos/域中的授权 简单的例子如 protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>().Property<string>("TenantId").HasField("_tenantId"); // Configure
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);
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().Property(“TenantId”).HasField(“_TenantId”);
//配置实体筛选器
modelBuilder.Entity();
modelBuilder.Entity().HasQueryFilter(p=>!p.IsDeleted);
}
这就是微软的例子_tenantId将用于创建表达式,对于DbContext的每个实例,它将使用正确的_tenantId值
但我不希望从DB上下文配置所有authorizen,我希望注入它。差不多
public class AgreementAuthorization : IEntityAuthorization
{
private readonly string _legalEntityNumber;
public AgreementAuthorization(IAuthScope scope)
{
_legalEntityNumber = scope.LegalEntityNumber;
}
public void Build(ModelBuilder builder)
{
builder
.Entity<Agreement>()
.HasQueryFilter(a => _legalEntityNumber == null || a.LegalEntity.Number == _legalEntityNumber);
}
}
public class MyDbContext : DbContext
{
private IEnumerable<IEntityAuthorization> _entityAuthorization;
MyDbContext(IEnumerable<IEntityAuthorization> entityAuthorization)
{
_entityAuthorization = entityAuthorization;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
builder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly);
_entityAuthorization.ForEach(a => a.Build(builder));
}
}
公共类协议授权:IEntityAuthorization
{
私有只读字符串_legalEntityNumber;
公共协议授权(IAuthScope范围)
{
_legalEntityNumber=scope.legalEntityNumber;
}
公共void生成(ModelBuilder)
{
建设者
.实体()
.HasQueryFilter(a=>u legalEntityNumber==null | | a.LegalEntity.Number==u legalEntityNumber);
}
}
公共类MyDbContext:DbContext
{
私有IEnumerable实体授权;
MyDbContext(IEnumerable entityAuthorization)
{
_entityAuthorization=entityAuthorization;
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
builder.ApplyConfigurationsFromAssembly(typeof(MyDbContext.Assembly));
_entityAuthorization.ForEach(a=>a.Build(builder));
}
}
这不起作用,每次查询都将针对null进行测试并通过。如果我将代码直接移动到DbContext,它就会工作。意思是_entityAuthorization直接取决于DbContext。From
筛选器不能包含对导航属性的引用
您正在引用导航属性LegalEntity
当您传入一个IEnumerable
时,这可能会影响您:
当前无法在上定义多个查询筛选器
同一实体-仅应用最后一个实体。但是,你可以
使用逻辑AND定义具有多个条件的单个筛选器
运算符(&&in C#)
更新:
我猜您需要直接引用
MyDbContext
的字段/属性,而不是在另一个对象中。插入一个类/接口,该类/接口允许访问要过滤的值,然后在OnModelCreating
方法的末尾配置过滤器。您可以对实体配置及其属性进行交互,以根据适用属性的存在情况应用所需的筛选器。每个DbContext类型、每个AppDomain只进行一次模型配置。这不是问题所在,问题在于表达式无法解析成员。在DbContext上定义表达式和成员时,同样的代码也会起作用(Builder仍然只在每个应用程序中执行一次)是否调用了Build()。但是当表达式被执行时,它无法解析_entityauthorizationmembers我可以如何构建一个能够解析正确数据的表达式吗?我也看到了这一点,有趣的是,当直接在DbContext上执行同样的操作时,它工作得很好。问题在于表达式无法解析在别处定义时用于查询的成员。这是一个企业级应用程序。直接在DbContext上定义事物不会导致iTunes更新;将筛选值存储在DbContext
中定义的字段/属性中,每个IEntityAuthorization实现都有自己的数据集。在DbContext上定义all会降低依赖性,你可以按自己的方式来做,也可以让它工作,@Anders;试一试,看看它是否有效,然后试着根据您的喜好定制它。它在企业场景中不起作用,我会在dbcobtext上抽象Set方法,所以我想我会在那里注入我自己的机制