Entity Framework 6 暂时禁用拦截
Posted
技术标签:
【中文标题】Entity Framework 6 暂时禁用拦截【英文标题】:Entity Framework 6 Disable Interception temporarily 【发布时间】:2017-02-01 16:03:52 【问题描述】:我正在使用IDbCommandTreeInterceptor
在我的模型上启用软删除。
System.Data.Entity.Infrastructure.Interception.DbInterception.Add(
new SoftDeleteInterception());
我希望能够暂时禁用拦截器,以便我可以选择一个“已删除”的实体进行审计。
但是,DbInterception
集合似乎是程序集范围的。
有没有什么方法可以创建一个新的DbContext
没有拦截?
或者甚至在每次创建时将拦截器添加到DbContext
的方法?
【问题讨论】:
嗨,你知道怎么做吗? @jekcom 不幸的是,没有。我最终不得不对我的上下文进行一些(疯狂的)反思,以从中获得我想要的东西。如果你找到方法,请告诉我。 我实际上解决了它(有点)。将在这里发布答案,可能会有所帮助 【参考方案1】:我用附加属性扩展了我的数据库上下文类
[DbConfigurationType(typeof(DbConfig))]
public partial class YourEntitiesDB
public bool IgnoreSoftDelete get; set;
然后在 TreeCreated(...) 方法中检查此标志,如果为 true,则它不会进一步进入 QueryVisitor
public class SoftDeleteInterceptor : IDbCommandTreeInterceptor
public SoftDeleteInterceptor()
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
var db = interceptionContext.DbContexts.FirstOrDefault() as YourEntitiesDB;
if (db!=null && db.IgnoreSoftDelete)
// Ignore soft delete interseptor (Used in archives)
return;
if (interceptionContext.OriginalResult.DataSpace == DataSpace.CSpace)
var queryCommand = interceptionContext.Result as DbQueryCommandTree;
if (queryCommand != null)
var newQuery = queryCommand.Query.Accept(new SoftDeleteQueryVisitor());
interceptionContext.Result = new DbQueryCommandTree(
queryCommand.MetadataWorkspace,
queryCommand.DataSpace,
newQuery);
var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree;
if (deleteCommand != null)
var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType);
if (column != null)
var setClauses = new List<DbModificationClause>();
var table = (EntityType)deleteCommand.Target.VariableType.EdmType;
if (table.Properties.Any(p => p.Name == column))
setClauses.Add(DbExpressionBuilder.SetClause(
DbExpressionBuilder.Property(
DbExpressionBuilder.Variable(deleteCommand.Target.VariableType, deleteCommand.Target.VariableName),
column),
DbExpression.FromBoolean(true)));
var update = new DbUpdateCommandTree(
deleteCommand.MetadataWorkspace,
deleteCommand.DataSpace,
deleteCommand.Target,
deleteCommand.Predicate,
setClauses.AsReadOnly(),
null);
interceptionContext.Result = update;
为了使用它,我只需在需要时将标志设置为 true
YuorEntitiesDB DB = new YuorEntitiesDB();
DB.IgnoreSoftDelete = true;
DB.Records.Where(...)
【讨论】:
伙计,我发誓我试过了,但没用,但看起来它解决了问题。谢谢! 更新答案,为此您还需要包括 AsNoTracking() @BlackTigerX 你能解释一下为什么你需要使用 AsNoTracking() 吗?我个人不使用它,它工作正常 我也无法让它工作 - 只有第一次它似乎按预期运行。似乎 TreeCreated 方法仅在第一个查询 pr 上运行。实体类型(然后缓存?)。因此,将 IgnoreSoftDelete 设置为 true 将在第一次查询时起作用,但将属性更改回 false 随后将不起作用。无论是否重新创建实体实例,此行为都是正确的。请详细说明@jekcom,如果你能让它工作......在这种情况下,我一定会遗漏一些东西。 @MichaelH.Pedersen TreeCreated 只有在您枚举查询后才会被访问。例如。如果你做 DB.Records.ToList() 你会看到它正在被访问。如果没有看到代码,我无法为您提供太多帮助。因此,如果您愿意,可以使用无效的代码打开一个新问题,我们会尽力提供帮助以上是关于Entity Framework 6 暂时禁用拦截的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework Core中的日志记录与拦截器
Entity Framework Core 中的日志记录与拦截器
如何在 Entity Framework 4.3.1 中禁用迁移?
如何在 Entity Framework 4.3.1 中禁用迁移?