public static DbExpression Convert(DynamicFilterDefinition filter, DbExpressionBinding binding, DbContext dbContext, DataSpace dataSpace) { var visitor = new LambdaToDbExpressionVisitor(filter, binding, dbContext, dataSpace); var expression = visitor.Visit(filter.Predicate) as LambdaExpression; var dbExpression = visitor.GetDbExpressionForExpression(expression.Body); if (dbExpression is DbPropertyExpression) { // Special case to handle a condition that is just a plain "boolFlag" or a nullable generic condition. // For a nullable type, we only get here when the filter has either not specified a value for the nullable // parameter or it has specified "null" - both evaluate the same as far as the method prototypes can tell // since the method signature is "param = null". This needs to generate a sql "is null" condition. // Otherwise, no param value was specified so we are assuming that we need to generate a "positive" // condition. i.e. the filter just said "b.prop" which generally means "b.prop == true". // To generate that condition correctly for all types (may not necessarily be a bool), we create a condition // like "!(b.prop == [defaultValue])" if (IsNullableType(expression.Body.Type)) { dbExpression = DbExpressionBuilder.IsNull(dbExpression); } else { var defaultValue = DbExpressionBuilder.Constant(dbExpression.ResultType, Activator.CreateInstance(expression.Body.Type)); dbExpression = DbExpressionBuilder.Not(DbExpressionBuilder.Equal(dbExpression, defaultValue)); } } return(dbExpression); }
public static DbExpression Convert(DynamicFilterDefinition filter, DbExpressionBinding binding, ObjectContext objectContext) { var visitor = new LambdaToDbExpressionVisitor(filter, binding, objectContext); var expression = visitor.Visit(filter.Predicate) as LambdaExpression; return(visitor.GetDbExpressionForExpression(expression.Body)); }
internal static void SetSqlParameters(this DbContext context, DbCommand command) { foreach (DbParameter param in command.Parameters) { // Item1 = Filter Name // Item2 = Parameter/Column Name var filterNameAndParam = DynamicFilterDefinition.GetFilterAndParamFromDBParameter(param.ParameterName); if (filterNameAndParam == null) { continue; // Not dynamic filter param } object value = context.GetFilterParameterValue(filterNameAndParam.Item1, filterNameAndParam.Item2); // If not found, leave as the default that EF assigned (which will be a DBNull) if (value == null) { continue; } // Check to see if it's a collection. If so, this is an "In" parameter var valueType = value.GetType(); if (valueType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(valueType)) { // Generic collection. The EF query created for this collection was an '=' condition. // We need to convert this into an 'in' clause so that we can dynamically set the // values in the collection. SetParameterList(value as IEnumerable, param, command, IsOracle(context)); context.Database.Log(string.Format("Manually replaced single parameter value with list, new SQL=\r\n{0}", command.CommandText)); } else { param.Value = value; } } }
internal static void SetSqlParameters(this DbContext context, DbCommand command) { foreach (DbParameter param in command.Parameters) { // Item1 = Filter Name // Item2 = Parameter/Column Name var filterNameAndParam = DynamicFilterDefinition.GetFilterAndParamFromDBParameter(param.ParameterName); if (filterNameAndParam == null) { continue; // Not dynamic filter param } object value = context.GetFilterParameterValue(filterNameAndParam.Item1, filterNameAndParam.Item2); // If not found, set to DBNull. It should already be set to that, but it's not in Postgre and we get // errors if we don't do that now. if (value == null) { if (filterNameAndParam.Item2 == DynamicFilterConstants.FILTER_DISABLED_NAME) { // This is the "is disabled" param and the filter is not disabled. There are cases where // including the "OR (@DynamicFilterParam_1 IS NOT NULL)" clause causes problems with // SQL Server index usage (it may decide not to use a multi-column index where the first // column is the filtered column and another column is also included in the where clause). // See issue #53. // So we're manually removing that entire condition from the sql. This will not remove the // parameter from being sent, but it will not be part of the sql statement. RemoveFilterDisabledConditionFromQuery(command, param); #if (DEBUG) if (!string.IsNullOrEmpty(command.CommandText) && command.CommandText.Contains(param.ParameterName)) { throw new ApplicationException(string.Format("CommandText still contains ParameterName {0} after RemoveFilterDisabledConditionFromQuery", param.ParameterName)); } #endif } param.Value = DBNull.Value; } else { // Check to see if it's a collection. If so, this is an "In" parameter var valueType = value.GetType(); if (valueType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(valueType)) { // Generic collection. The EF query created for this collection was an '=' condition. // We need to convert this into an 'in' clause so that we can dynamically set the // values in the collection. SetParameterList(value as IEnumerable, param, command, IsOracle(context), IsMySql(context)); if (context.Database.Log != null) { context.Database.Log(string.Format("Manually replaced single parameter value with list, new SQL=\r\n{0}", command.CommandText)); } } else { param.Value = value; } } } }
private LambdaToDbExpressionVisitor(DynamicFilterDefinition filter, DbExpressionBinding binding, DbContext dbContext, DataSpace dataSpace) { _Filter = filter; _Binding = binding; _DbContext = dbContext; _ObjectContext = ((IObjectContextAdapter)dbContext).ObjectContext; _DataSpace = dataSpace; }
public DynamicFilterConvention(string filterName, Type entityType, LambdaExpression predicate, string columnName) { var configuration = Types().Where(entityType.IsAssignableFrom); configuration.Configure(ctc => { var filterDefinition = new DynamicFilterDefinition(filterName, predicate, columnName, ctc.ClrType); ctc.HasTableAnnotation(filterDefinition.AttributeName, filterDefinition); }); }
/// <summary> /// /// </summary> /// <param name="filterName"></param> /// <param name="entityType"></param> /// <param name="predicate"></param> /// <param name="columnName"></param> /// <param name="selectEntityTypeCondition">If not null, this delegate should return true if the filter should be applied to the given entity Type. /// False if not. Allows additional logic to be applied to determine if the filter should be applied to an Entity of type "TEntity". /// i.e. To apply the filter to all entities of a particular interface but not if those entities also implement another interface.</param> public DynamicFilterConvention(string filterName, Type entityType, LambdaExpression predicate, string columnName, Func <Type, bool> selectEntityTypeCondition) { var configuration = Types().Where(t => entityType.IsAssignableFrom(t) && ((selectEntityTypeCondition == null) || selectEntityTypeCondition(t))); configuration.Configure(ctc => { var filterDefinition = new DynamicFilterDefinition(filterName, predicate, columnName, ctc.ClrType); ctc.HasTableAnnotation(filterDefinition.AttributeName, filterDefinition); }); }
public static EntityTypeConfiguration <TEntity> Filter <TEntity>(this EntityTypeConfiguration <TEntity> config, string filterName, string columnName, object globalValue = null) where TEntity : class { filterName = ScrubFilterName(filterName); var filterDefinition = new DynamicFilterDefinition(filterName, null, columnName, typeof(TEntity)); config.HasTableAnnotation(filterDefinition.AttributeName, filterDefinition); if (globalValue != null) { SetFilterGlobalParameterValue(null, filterName, columnName, globalValue); } return(config); }
/// <summary> /// </summary> /// <param name="filterName"></param> /// <param name="entityType"></param> /// <param name="predicate"></param> /// <param name="columnName"></param> /// <param name="config">Options for how and when to apply this filter</param> public DynamicFilterConvention(string filterName, Type entityType, LambdaExpression predicate, string columnName, Func <DynamicFilterConfig, DynamicFilterOptions> config) { var options = (config == null) ? new DynamicFilterOptions() : config(new DynamicFilterConfig()); var id = Guid.NewGuid(); var configuration = Types().Where(t => entityType.IsAssignableFrom(t) && ((options.SelectEntityTypeCondition == null) || options.SelectEntityTypeCondition(t))); configuration.Configure(ctc => { var filterDefinition = new DynamicFilterDefinition(id, filterName, predicate, columnName, ctc.ClrType, options); ctc.HasTableAnnotation(filterDefinition.AttributeName, filterDefinition); }); }
public static DbExpression Convert(DynamicFilterDefinition filter, DbExpressionBinding binding, DbContext dbContext, DataSpace dataSpace) { var visitor = new LambdaToDbExpressionVisitor(filter, binding, dbContext, dataSpace); var expression = visitor.Visit(filter.Predicate) as LambdaExpression; var dbExpression = visitor.GetDbExpressionForExpression(expression.Body); if (dbExpression is DbPropertyExpression) { // Special case to handle a condition that is just a plan "boolFlag" condition. // In order for the sql to generate correct, we need to turn this into "boolFlag = true" // Figuring out the defaultValue like this should produce the default (0, false, empty) value for the type // we are working with. So checking then generating a condition of "not (@var = defaultValue)" should produce // the correct condition. var defaultValue = DbExpressionBuilder.Constant(dbExpression.ResultType, Activator.CreateInstance(expression.Body.Type)); dbExpression = DbExpressionBuilder.Not(DbExpressionBuilder.Equal(dbExpression, defaultValue)); } return(dbExpression); }
private LambdaToDbExpressionVisitor(DynamicFilterDefinition filter, DbExpressionBinding binding, ObjectContext objectContext) { _Filter = filter; _Binding = binding; _ObjectContext = objectContext; }