是否可以拦截READ操作?
在实体框架的核心,您可以覆盖DbContext
SaveChanges
/SaveChangesAsync
方法和基于像不同的状态:EntityState.Added
或EntityState.Modified
或EntityState.Deleted
,您可以创建什么时候和谁创建,修改或删除某些记录一些审计解决方案。您可以在操作前后保存实体的状态。这里所有的好东西都很完美是否可以拦截READ操作?
我们可以为读取/查询/选择/查看操作做类似的事吗?
我挖了一点,发现IQueryable
的实际执行是由EntityQueryProvider : IAsyncQueryProvider, IQueryProvider
完成的。
所以...你覆盖默认EntityQueryProvider
做记录:
public class LoggingQueryProvider : EntityQueryProvider
{
public LoggingQueryProvider(IQueryCompiler queryCompiler) : base(queryCompiler) { }
public override object Execute(Expression expression)
{
var result = base.Execute(expression);
//log
return result;
}
public override TResult Execute<TResult>(Expression expression)
{
var result = base.Execute<TResult>(expression);
//log
return result;
}
public override IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression)
{
var result = base.ExecuteAsync<TResult>(expression);
//log
return result;
}
public override Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
var result = base.ExecuteAsync<TResult>(expression, cancellationToken);
//log
return result;
}
}
和StartUp.ConfigureServices(IServiceCollection services)
services.AddDbContext<XPContext>(builder =>
builder
.UseSqlServer(Configuration["TryDBConnectionString"])
.ReplaceService<IAsyncQueryProvider, LoggingQueryProvider>()
);
配置的DbContext当你注册它这不是很简单的,但你应该能够从表达式中获得一些信息,如实体类型,并且您显然可以访问实际结果。异步方法看起来有点复杂,但...
我喜欢扩展查询提供者的想法,但你打算如何在没有dbContext的情况下登录到数据库? –
想到使用单独的'DbContext' ... –
大多数策略都依赖于覆盖SaveChanges()
来审计数据,但您也可以通过重写Dispose()
方法来访问其他数据。
当从数据库查询数据时,它将被添加到dbContext中,如果它被读取但没有被更改,它应该有EntityState.Unchanged
。
假设每个请求的新实例的一个典型的web应用风格DbContext
范围然后通过ID的查询将意味着有一个在ChangeTracker
与该状态的单个条目的DbContext
设置时。
你可以尝试这样的事:
public override void Dispose()
{
var unchanged = ChangeTracker.Entries()
.Where(x => x.EntityState == EntityState.Unchanged);
// log your unchanged entries here
base.Dispose();
}
这不完全万无一失,因为你可能会在一个创建/更新过程中检索某些表数据作为验证的一部分,或者你可能跨越共用同一个上下文多个存储库,因此您需要考虑哪些实体需要仔细审核以及使用哪种访问模式
如何查询'AsNoTracking()'? –
@GertArnold正如我所说 - 不是万无一失。假设OP可以控制所有查询。现在你提到它'AsNoChangeTracking()'可以添加一个从审计中排除某些查询的细粒度方法。 –
我建议您在更高级别进行日志记录。例如,如果您使用的是WebApi,则可以在OWIN管道级别登录,从而记录信息请求。
通过记录低端数据来进行第二次猜测,并重新读取丑陋的数据,并最终导致效率低下。
为什么这应该关闭?这个问题有什么问题? – user2818430
看看如果https://stackoverflow.com/questions/45132553/objectstatemanager-objectstatemanagerchanged-in-entity-framework-core/45192985#45192985可以帮助 –
由此你的意思是如何记录SELECT语句或不同的东西? – Evk