public override DbExpression Visit(DbScanExpression expression) { var column = SoftDeleteAttribute.GetSoftDeleteColumnName(expression.Target.ElementType); if (column != null) { // Just because the entity has the soft delete annotation doesn't mean that // this particular table has the column. This occurs in situation like TPT // inheritance mapping and entity splitting where one type maps to multiple // tables. // We only apply the filter if the column is actually present in this table. // If not, then the query is going to be joining to the table that does have // the column anyway, so the filter will still be applied. var table = (EntityType)expression.Target.ElementType; if (table.Properties.Any(p => p.Name == column)) { var binding = DbExpressionBuilder.Bind(expression); var predicate = binding.VariableType.Variable(binding.VariableName).Property(column).NotEqual(DbExpression.FromBoolean(true)); return(binding.Filter(predicate)); } } return(base.Visit(expression)); }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace) { 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) { // Just because the entity has the soft delete annotation doesn't mean that // this particular table has the column. This occurs in situation like TPT // inheritance mapping and entity splitting where one type maps to multiple // tables. // If the table doesn't have the column we just want to leave the row unchanged // since it will be joined to the table that does have the column during query. // We can't no-op, so we just generate an UPDATE command that doesn't set anything. 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; } } } }