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); return(DbExpressionBuilder.Filter( binding, DbExpressionBuilder.NotEqual( DbExpressionBuilder.Property( DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName), column), DbExpression.FromBoolean(true)))); } } return(base.Visit(expression)); }
public override DbExpression Visit(DbScanExpression expression) { var table = (EntityType)expression.Target.ElementType; //only need to check for IsDeleted column //IsDeleted and IsNew always go side by side in BaseEntity if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(base.Visit(expression)); } var binding = expression.Bind(); //return binding.Filter( // binding.VariableType // .Variable(binding.VariableName) // .Property(IsDeletedColumnName) // .Equal(DbExpression.FromBoolean(false))); var filter = DbExpressionBuilder.And( binding.VariableType .Variable(binding.VariableName) .Property(IsDeletedColumnName) .Equal(DbExpression.FromBoolean(false)), binding.VariableType .Variable(binding.VariableName) .Property(IsNewColumnName) .Equal(DbExpression.FromBoolean(false))); return(binding.Filter(filter)); }
private DbCommandTree HandleDeleteCommand(DbDeleteCommandTree deleteCommand) { var setClauses = new List <DbModificationClause>(); var table = (EntityType)deleteCommand.Target.VariableType.EdmType; if (table.Properties.All(p => p.Name != Constants.IS_DELETED_COLUMN_NAME)) { return(deleteCommand); } var now = m_DateTimeProvider.GetUtcNow(); setClauses.Add(DbExpressionBuilder.SetClause( deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(Constants.IS_DELETED_COLUMN_NAME), DbExpression.FromBoolean(true))); setClauses.Add(DbExpressionBuilder.SetClause( deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(Constants.DELETED_COLUMN_NAME), DbExpression.FromDateTime(now))); return(new DbUpdateCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, deleteCommand.Predicate, setClauses.AsReadOnly(), null)); }
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; } } } }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace) { return; } 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) { return; } var column = SoftDeleteAttribute.GetSoftDeleteColumnName(deleteCommand.Target.VariableType.EdmType); if (column == null) { return; } var setClauses = new List <DbModificationClause>(); var table = (EntityType)deleteCommand.Target.VariableType.EdmType; if (table.Properties.Any(p => p.Name == column)) { setClauses.Add(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, setClauses.AsReadOnly(), null); interceptionContext.Result = update; }
public override DbExpression Visit(DbScanExpression expression) { if (!expression.Target.ElementType.MetadataProperties.Any(mp => mp.Name.EndsWith("customannotation:" + AbpEfConsts.SoftDeleteCustomAnnotationName))) { return(base.Visit(expression)); } var binding = expression.Bind(); return(binding .Filter(binding.VariableType.Variable(binding.VariableName) .Property("IsDeleted")//TODO: User may want to bind to another column name. It's better to use actual database column name .Equal(DbExpression.FromBoolean(false)))); }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace) { var queryCommand = interceptionContext.Result as DbQueryCommandTree; if (queryCommand != null) { var context = (DataContext)interceptionContext.DbContexts.Single(c => c is DataContext); if (context.SoftDeleteFilterIsActive) { 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 setClause = 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, new List <DbModificationClause> { setClause }.AsReadOnly(), null); interceptionContext.Result = update; } } } }
public override DbExpression Visit(DbScanExpression expression) { var table = (EntityType)expression.Target.ElementType; if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(base.Visit(expression)); } var binding = expression.Bind(); return(binding.Filter( binding.VariableType .Variable(binding.VariableName) .Property(IsDeletedColumnName) .NotEqual(DbExpression.FromBoolean(true)))); }
public override DbExpression Visit(DbScanExpression expression) { var columnName = SoftDeleteAttribute.GetSoftDeleteColumnName(expression.Target.ElementType); var entityType = (EntityType)expression.Target.ElementType; if (columnName == null || entityType.Properties.All(p => p.Name != columnName)) { return(base.Visit(expression)); } var binding = expression.Bind(); return(binding.Filter( binding.VariableType .Variable(binding.VariableName) .Property(columnName) .NotEqual(DbExpression.FromBoolean(true)))); }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace) { //This was Rowan Miller's example for filtering out IsDeleteds, but I'm going to try Jimmy Bogard's method instead. 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 setClause = 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, new List <DbModificationClause> { setClause }.AsReadOnly(), null); interceptionContext.Result = update; } } } }
public override DbExpression Visit(DbScanExpression expression) { const string column = "IsActive"; var table = (EntityType)expression.Target.ElementType; if (!table.Properties.Any(p => p.Name == column)) { return(base.Visit(expression)); } var binding = expression.Bind(); return (binding.Filter( binding.VariableType.Variable(binding.VariableName) .Property(column) .Equal(DbExpression.FromBoolean(true)))); }
public override DbExpression Visit(DbScanExpression expression) { var column = ColumnAnnotationAttribute.GetColumnName <TrackDeletedBitAttribute>(expression.Target.ElementType); // var column = TrackDeletedBitAttribute.GetColumnName(expression.Target.ElementType); if (column != null) { var binding = expression.Bind(); return(binding .Filter(binding.VariableType.Variable(binding.VariableName) .Property(column) .NotEqual(DbExpression.FromBoolean(true)) .Or(binding.VariableType.Variable(binding.VariableName) .Property(column).IsNull()))); } else { return(base.Visit(expression)); } }
public override DbExpression Visit(DbScanExpression expression) { var column = SoftDeleteAttribute.GetColumnName(expression.Target.ElementType); if (column != null) { var binding = DbExpressionBuilder.Bind(expression); return(DbExpressionBuilder.Filter( binding, DbExpressionBuilder.NotEqual( DbExpressionBuilder.Property( DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName), column), DbExpression.FromBoolean(true)))); } else { return(base.Visit(expression)); } }
private static DbCommandTree HandleDeleteCommand(DbDeleteCommandTree deleteCommand) { var setClauses = new List <DbModificationClause>(); var table = (EntityType)deleteCommand.Target.VariableType.EdmType; if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(deleteCommand); } setClauses.Add(DbExpressionBuilder.SetClause( deleteCommand.Target.VariableType.Variable(deleteCommand.Target.VariableName).Property(IsDeletedColumnName), DbExpression.FromBoolean(true))); return(new DbUpdateCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, deleteCommand.Predicate, setClauses.AsReadOnly(), null)); }
public override DbExpression Visit(DbScanExpression expression) { var column = this.GetSoftDeleteColumnName(expression.Target.ElementType); if (column != null) { var table = (EntityType)expression.Target.ElementType; if (table.Properties.Any(p => p.Name == column)) { var binding = DbExpressionBuilder.Bind(expression); return(DbExpressionBuilder.Filter( binding, DbExpressionBuilder.NotEqual( DbExpressionBuilder.Property( DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName), column), DbExpression.FromBoolean(true)))); } } return(base.Visit(expression)); }
public override DbExpression Visit(DbScanExpression expression) { var table = (EntityType)expression.Target.ElementType; if (table.Properties.All(p => p.Name != IsDeletedColumnName)) { return(base.Visit(expression)); } DbExpression newConditionExpression = null; var binding = expression.Bind(); if (table.Properties.Any(p => p.Name == IsDeletedColumnName)) { var param = DbExpression.FromBoolean(false); var columnProperty = DbExpressionBuilder.Property(DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName), IsDeletedColumnName); if ((columnProperty.ResultType.EdmType.FullName == "Edm.Boolean") && param.ResultType.EdmType.FullName.StartsWith("Oracle", StringComparison.CurrentCultureIgnoreCase) && (param.ResultType.EdmType.Name == "number")) { newConditionExpression = DbExpressionBuilder.Equal(DbExpressionBuilder.CastTo(columnProperty, param.ResultType), param); } else { newConditionExpression = DbExpressionBuilder.Equal(columnProperty, param); } } return(DbExpressionBuilder.Filter(binding, newConditionExpression)); //return binding.Filter( // binding.VariableType // .Variable(binding.VariableName) // .Property(IsDeletedColumnName) // .Equal(DbExpression.FromBoolean(false))); }
protected override Expression VisitConstant(ConstantExpression node) { var expression = base.VisitConstant(node); var type = node.Type; if (IsNullableType(type)) { var genericArgs = type.GetGenericArguments(); if ((genericArgs != null) && (genericArgs.Length == 1)) { type = genericArgs[0]; } } if (type == typeof(byte[])) { MapExpressionToDbExpression(expression, DbExpression.FromBinary((byte[])node.Value)); } else if (type == typeof(bool)) { MapExpressionToDbExpression(expression, DbExpression.FromBoolean((bool?)node.Value)); } else if (type == typeof(byte)) { MapExpressionToDbExpression(expression, DbExpression.FromByte((byte?)node.Value)); } else if (type == typeof(DateTime)) { MapExpressionToDbExpression(expression, DbExpression.FromDateTime((DateTime?)node.Value)); } else if (type == typeof(DateTimeOffset)) { MapExpressionToDbExpression(expression, DbExpression.FromDateTimeOffset((DateTimeOffset?)node.Value)); } else if (type == typeof(decimal)) { MapExpressionToDbExpression(expression, DbExpression.FromDecimal((decimal?)node.Value)); } else if (type == typeof(double)) { MapExpressionToDbExpression(expression, DbExpression.FromDouble((double?)node.Value)); } else if (type == typeof(Guid)) { MapExpressionToDbExpression(expression, DbExpression.FromGuid((Guid?)node.Value)); } else if (type == typeof(Int16)) { MapExpressionToDbExpression(expression, DbExpression.FromInt16((Int16?)node.Value)); } else if (type == typeof(Int32)) { MapExpressionToDbExpression(expression, DbExpression.FromInt32((Int32?)node.Value)); } else if (type.IsEnum) { MapExpressionToDbExpression(expression, DbExpression.FromInt32((Int32)node.Value)); } else if (type == typeof(Int64)) { MapExpressionToDbExpression(expression, DbExpression.FromInt64((Int64?)node.Value)); } else if (type == typeof(float)) { MapExpressionToDbExpression(expression, DbExpression.FromSingle((float?)node.Value)); } else if (type == typeof(string)) { MapExpressionToDbExpression(expression, DbExpression.FromString((string)node.Value)); } else { throw new NotImplementedException(string.Format("Unhandled Type of {0} for Constant value {1} in LambdaToDbExpressionVisitor.VisitConstant", node.Type.Name, node.Value ?? "null")); } return(expression); }
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext) { if (interceptionContext.Result.DataSpace == DataSpace.SSpace && interceptionContext.DbContexts.All(con => con.GetType().GetCustomAttribute <TrackDisabledAttribute>() == null)) { #region Query var queryCommand = interceptionContext.Result as DbQueryCommandTree; if (queryCommand != null) { var newQuery = queryCommand.Query.Accept(new TrackingQueryVisitor()); interceptionContext.Result = new DbQueryCommandTree( queryCommand.MetadataWorkspace, queryCommand.DataSpace, newQuery); } #endregion #region Delete var deleteCommand = interceptionContext.Result as DbDeleteCommandTree; if (deleteCommand != null) { var bitColumn = ColumnAnnotationAttribute.GetColumnName <TrackDeletedBitAttribute>(deleteCommand.Target.VariableType.EdmType); var dateColumn = ColumnAnnotationAttribute.GetColumnName <TrackDeletedDateAttribute>(deleteCommand.Target.VariableType.EdmType); var identityColumn = ColumnAnnotationAttribute.GetColumnName <TrackDeletedIdentityAttribute>(deleteCommand.Target.VariableType.EdmType); var clauses = new List <DbModificationClause>(); if (bitColumn != null) { clauses.Add(DbExpressionBuilder.SetClause(deleteCommand.Target.Variable.Property(bitColumn), DbExpression.FromBoolean(true))); if (dateColumn != null) { clauses.Add(DbExpressionBuilder.SetClause(deleteCommand.Target.Variable.Property(dateColumn), DbExpression.FromDateTimeOffset(TimeZoneInfo.ConvertTime(timeProvider.NowOffsetted().Add(_dateTimeAdjustment), getCurrentTimeZoneFunction())))); } if (identityColumn != null) { clauses.Add(DbExpressionBuilder.SetClause(deleteCommand.Target.Variable.Property(identityColumn), DbExpression.FromString(getCurrentIdentityFunction()))); } } if (clauses.Count > 0) { //Add this constant clause to trace deletions on update command clauses.Add(DbExpressionBuilder.SetClause(DbExpressionBuilder.Constant(137), DbExpressionBuilder.Constant(137))); interceptionContext.Result = new DbUpdateCommandTree( deleteCommand.MetadataWorkspace, deleteCommand.DataSpace, deleteCommand.Target, deleteCommand.Predicate, clauses.AsReadOnly(), null); } } #endregion #region Insert var insertCommand = interceptionContext.Result as DbInsertCommandTree; if (insertCommand != null) { var dateColumn = ColumnAnnotationAttribute.GetColumnName <TrackCreatedDateAttribute>(insertCommand.Target.VariableType.EdmType); var identityColumn = ColumnAnnotationAttribute.GetColumnName <TrackCreatedIdentityAttribute>(insertCommand.Target.VariableType.EdmType); var clauses = insertCommand.SetClauses.ToList(); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedBitAttribute>(insertCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedDateAttribute>(insertCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedIdentityAttribute>(insertCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackModifiedDateAttribute>(insertCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackModifiedIdentityAttribute>(insertCommand.Target.VariableType.EdmType)); if (dateColumn != null) { AddOrReplaceClause(clauses, DbExpressionBuilder.SetClause(insertCommand.Target.Variable.Property(dateColumn), DbExpression.FromDateTimeOffset(TimeZoneInfo.ConvertTime(timeProvider.NowOffsetted().Add(_dateTimeAdjustment), getCurrentTimeZoneFunction())))); } if (identityColumn != null) { AddOrReplaceClause(clauses, DbExpressionBuilder.SetClause(insertCommand.Target.Variable.Property(identityColumn), DbExpression.FromString(getCurrentIdentityFunction()))); } if (dateColumn != null || (identityColumn != null)) { interceptionContext.Result = new DbInsertCommandTree( insertCommand.MetadataWorkspace, insertCommand.DataSpace, insertCommand.Target, clauses.AsReadOnly(), null); } } #endregion #region Update var updateCommand = interceptionContext.Result as DbUpdateCommandTree; if (updateCommand != null) { var dateColumn = ColumnAnnotationAttribute.GetColumnName <TrackModifiedDateAttribute>(updateCommand.Target.VariableType.EdmType); var identityColumn = ColumnAnnotationAttribute.GetColumnName <TrackModifiedIdentityAttribute>(updateCommand.Target.VariableType.EdmType); var clauses = updateCommand.SetClauses.ToList(); var traceDeleteionsClause = clauses.FirstOrDefault(c => ((DbSetClause)c).Property is DbConstantExpression && ((DbConstantExpression)((DbSetClause)c).Property).Value is int && ((int)((DbConstantExpression)((DbSetClause)c).Property).Value) == 137 && ((DbSetClause)c).Value is DbConstantExpression && ((DbConstantExpression)((DbSetClause)c).Value).Value is int && ((int)((DbConstantExpression)((DbSetClause)c).Value).Value) == 137 ); if (traceDeleteionsClause != null) { //This command is derived from a deletion operation clauses.Remove(traceDeleteionsClause); } else { RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedBitAttribute>(updateCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedDateAttribute>(updateCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackDeletedIdentityAttribute>(updateCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackCreatedDateAttribute>(updateCommand.Target.VariableType.EdmType)); RemoveClause(clauses, ColumnAnnotationAttribute.GetColumnName <TrackCreatedIdentityAttribute>(updateCommand.Target.VariableType.EdmType)); if (dateColumn != null) { AddOrReplaceClause(clauses, DbExpressionBuilder.SetClause(updateCommand.Target.Variable.Property(dateColumn), DbExpression.FromDateTimeOffset(TimeZoneInfo.ConvertTime(timeProvider.NowOffsetted().Add(_dateTimeAdjustment), getCurrentTimeZoneFunction())))); } if (identityColumn != null) { AddOrReplaceClause(clauses, DbExpressionBuilder.SetClause(updateCommand.Target.Variable.Property(identityColumn), DbExpression.FromString(getCurrentIdentityFunction()))); } } if (dateColumn != null || (identityColumn != null)) { interceptionContext.Result = new DbUpdateCommandTree( updateCommand.MetadataWorkspace, updateCommand.DataSpace, updateCommand.Target, updateCommand.Predicate, clauses.AsReadOnly(), null); } } #endregion } }
//public override DbExpression Visit(DbFilterExpression expression) //{ // // If the query contains it's own filter condition (in a .Where() for example), this will be called // // before Visit(DbScanExpression). And it will contain the Predicate specified in that filter. // // Need to inject our dynamic filters here and then 'and' the Predicate. This is necessary so that // // the expressions are properly ()'d. // // It also allows us to attach our dynamic filter into the same DbExpressionBinding so it will avoid // // creating a new sub-query in MS SQL Server. // var predicate = VisitExpression(expression.Predicate); // Visit the predicate so filters will be applied to any child properties inside it (issue #61) // string entityName = expression.Input.Variable.ResultType.EdmType.Name; // //var containers = _ObjectContext.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace).First(); // // var filterList = FindFiltersForEntitySet(expression.Input.Variable.ResultType.EdmType.MetadataProperties, containers); // var newFilterExpression = BuildFilterExpressionWithDynamicFilters(entityName, new List<string>() { IsDeletedColumnName }, expression.Input, predicate); // if (newFilterExpression != null) // { // // If not null, a new DbFilterExpression has been created with our dynamic filters. // return newFilterExpression; // } // return base.Visit(expression); //} //public override DbExpression Visit(DbScanExpression expression) //{ // var table = (EntityType)expression.Target.ElementType; // if (table.Properties.All(p => p.Name != IsDeletedColumnName)) // { // return base.Visit(expression); // } // string entityName = expression.Target.Name; // var baseResult = base.Visit(expression); // var binding = DbExpressionBuilder.Bind(baseResult); // var newFilterExpression = BuildFilterExpressionWithDynamicFilters(entityName, new List<string>() { IsDeletedColumnName }, binding, null); // if (newFilterExpression != null) // { // // If not null, a new DbFilterExpression has been created with our dynamic filters. // return newFilterExpression; // } // return baseResult; //} //public override DbExpression Visit(DbJoinExpression expression) //{ // DbExpressionBinding left = this.VisitExpressionBinding(expression.Left); // DbExpressionBinding right = this.VisitExpressionBinding(expression.Right); // var rightProperty = DbExpressionBuilder.Property(right.Variable, IsDeletedColumnName); // var predicateExpression = DbExpressionBuilder.Equal(rightProperty, DbExpression.FromBoolean(false)); // var joinCondition = DbExpressionBuilder.And(expression.JoinCondition, predicateExpression); // DbExpression newExpression = expression; // //only re-create the join if something changed // //if (!ReferenceEquals(expression.Left, left) // // || !ReferenceEquals(expression.Right, right) // // || !ReferenceEquals(expression.JoinCondition, joinCondition)) // //{ // switch (expression.ExpressionKind) // { // case DbExpressionKind.InnerJoin: // newExpression = DbExpressionBuilder.InnerJoin(left, right, joinCondition); // break; // case DbExpressionKind.LeftOuterJoin: // newExpression = DbExpressionBuilder.LeftOuterJoin(left, right, joinCondition); // break; // case DbExpressionKind.FullOuterJoin: // newExpression = DbExpressionBuilder.FullOuterJoin(left, right, joinCondition); // break; // } // //} // return newExpression; //} private DbFilterExpression BuildFilterExpressionWithDynamicFilters(string entityName, IEnumerable <string> filterList, DbExpressionBinding binding, DbExpression predicate) { if (!filterList.Any()) { return(null); } var edmType = binding.VariableType.EdmType as EntityType; if (edmType == null) { return(null); } List <DbExpression> conditionList = new List <DbExpression>(); HashSet <string> processedFilterNames = new HashSet <string>(); foreach (var filter in filterList) { if (processedFilterNames.Contains(filter)) { continue; // Already processed this filter - attribute was probably inherited in a base class } processedFilterNames.Add(filter); DbExpression dbExpression; if (!string.IsNullOrEmpty(filter)) { // Single column equality filter // Need to map through the EdmType properties to find the actual database/cspace name for the entity property. // It may be different from the entity property! var edmProp = edmType.Properties.Where(p => p.MetadataProperties.Any(m => m.Name == "PreferredName" && m.Value.Equals(filter))).FirstOrDefault(); if (edmProp == null) { continue; // ??? } // database column name is now in edmProp.Name. Use that instead of filter.ColumnName var columnProperty = DbExpressionBuilder.Property(DbExpressionBuilder.Variable(binding.VariableType, binding.VariableName), edmProp.Name); //var param = columnProperty.Property.TypeUsage.Parameter(filter.CreateDynamicFilterName(filter.ColumnName, DataSpace.SSpace)); var param = DbExpression.FromBoolean(false); // When using SSpace, need some special handling for an Oracle Boolean property. // Not necessary when using CSpace since the translation into the Oracle types has not happened yet. if ((columnProperty.ResultType.EdmType.FullName == "Edm.Boolean") && param.ResultType.EdmType.FullName.StartsWith("Oracle", StringComparison.CurrentCultureIgnoreCase) && (param.ResultType.EdmType.Name == "number")) // Don't trust Oracle's type name to stay the same... { // Special handling needed for columnProperty boolean. For some reason, the Oracle EF driver does not correctly // set the ResultType to a number(1) in columnProperty like it does in columnProperty.Property.TypeUsage. That // results in us trying to do a comparison of a Boolean to a number(1) which causes DbExpressionBuilder.Equal // to throw an exception. To get this to process correctly, we need to do a cast on the columnProperty to // "number(1)" so that it matches the param.ResultType. And that results in the sql sent to Oracle converting // the column to the type that it already is... dbExpression = DbExpressionBuilder.Equal(DbExpressionBuilder.CastTo(columnProperty, param.ResultType), param); } else { dbExpression = DbExpressionBuilder.Equal(columnProperty, param); } conditionList.Add(dbExpression); } } int numConditions = conditionList.Count; DbExpression newPredicate; switch (numConditions) { case 0: return(null); case 1: newPredicate = conditionList.First(); break; default: // Have multiple conditions. Need to append them together using 'and' conditions. newPredicate = conditionList.First(); for (int i = 1; i < numConditions; i++) { newPredicate = newPredicate.And(conditionList[i]); } break; } // 'and' the existing Predicate if there is one if (predicate != null) { newPredicate = newPredicate.And(predicate); } return(DbExpressionBuilder.Filter(binding, newPredicate)); }