我实现了 Rowan Miller 在TechEd 会议期间演示的软删除模式但是我遇到了一个直接的问题,因为我在我的 Code First 模型中使用了继承。第一个错误是在查询期间,因为我将 IsDeleted 属性放在我的超类型(基类)上,但是当我截获子类型的查询并尝试添加过滤器时,EF 抱怨该类型上没有这样的属性。很公平,我将属性移到了子类型中,并且效果还不错。但是在删除时,命令树拦截器将子类型的删除更改为“更新集 isdeleted=1”,但 EF 还为超类型(基类)生成了删除。这导致数据库中出现外键约束错误。这有点痛苦,但我可以通过禁止执行超类型的删除命令来解决它。
但是,我在拦截上下文中找不到 SuppressExecution 方法,如果我将结果设置为 null,我会得到一个 nullref 异常。我想我需要一些方法来用 NullDbCommand 或类似的命令替换命令。有任何想法吗?
public class CommandTreeInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace) return;
// Look for query and add 'IsDeleted = 0' filter.
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);
}
// Look for delete and change it to an update instead.
var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree;
if (deleteCommand != null)
{
// !!! Need to suppress this whole command for supertypes (base class).
var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.Variable.ResultType.EdmType);
if (column != null)
{
var setClause =
DbExpressionBuilder.SetClause(
deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName)
.Property(column), DbExpression.FromBoolean(true));
var update = new DbUpdateCommandTree(deleteCommand.MetadataWorkspace,
deleteCommand.DataSpace,
deleteCommand.Target,
deleteCommand.Predicate,
new List<DbModificationClause>{ setClause }.AsReadOnly(), null);
interceptionContext.Result = update;
}
}
}
}