This page covers the advanced features of SmartWhere, including specialized attributes, logical operators, and performance optimizations.
The TextualWhereClause
attribute provides advanced text search capabilities with multiple string methods.
public enum StringMethod
{
Contains, // LIKE '%value%'
NotContains, // NOT LIKE '%value%'
StartsWith, // LIKE 'value%'
NotStartsWith, // NOT LIKE 'value%'
EndsWith, // LIKE '%value'
NotEndsWith // NOT LIKE '%value'
}
public class TextualSearchRequest : IWhereClause
{
[TextualWhereClause(StringMethod.Contains)]
public string Title { get; set; }
[TextualWhereClause(StringMethod.StartsWith)]
public string Author { get; set; }
[TextualWhereClause(StringMethod.EndsWith)]
public string ISBN { get; set; }
}
public class AdvancedTextSearchRequest : IWhereClause
{
[TextualWhereClause("Title", StringMethod.Contains)]
public string TitleKeyword { get; set; }
[TextualWhereClause("Author.Name", StringMethod.StartsWith)]
public string AuthorFirstName { get; set; }
[TextualWhereClause("Publisher.Name", StringMethod.NotContains)]
public string ExcludePublisher { get; set; }
[TextualWhereClause("Description", StringMethod.NotEndsWith)]
public string ExcludeDescriptionEnding { get; set; }
}
public class CaseSensitiveSearchRequest : IWhereClause
{
[TextualWhereClause(StringMethod.Contains, CaseSensitive = true)]
public string ExactTitle { get; set; }
[TextualWhereClause(StringMethod.StartsWith, CaseSensitive = false)]
public string AuthorName { get; set; }
}
The ComparativeWhereClause
attribute enables numeric and date comparisons with various operators.
public enum ComparisonOperator
{
Equal, // =
NotEqual, // !=
GreaterThan, // >
NotGreaterThan, // !>
GreaterThanOrEqual, // >=
NotGreaterThanOrEqual, // !>=
LessThan, // <
NotLessThan, // !<
LessThanOrEqual, // <=
NotLessThanOrEqual // !<=
}
public class NumericSearchRequest : IWhereClause
{
[ComparativeWhereClause("Price", ComparisonOperator.GreaterThan)]
public decimal? MinPrice { get; set; }
[ComparativeWhereClause("Price", ComparisonOperator.LessThanOrEqual)]
public decimal? MaxPrice { get; set; }
[ComparativeWhereClause("Quantity", ComparisonOperator.GreaterThanOrEqual)]
public int? MinQuantity { get; set; }
[ComparativeWhereClause("Stock", ComparisonOperator.NotEqual)]
public int? ExcludeStock { get; set; }
}
public class DateSearchRequest : IWhereClause
{
[ComparativeWhereClause("PublishedDate", ComparisonOperator.GreaterThanOrEqual)]
public DateTime? StartDate { get; set; }
[ComparativeWhereClause("PublishedDate", ComparisonOperator.LessThanOrEqual)]
public DateTime? EndDate { get; set; }
[ComparativeWhereClause("CreatedDate", ComparisonOperator.LessThan)]
public DateTime? CreatedBefore { get; set; }
[ComparativeWhereClause("ModifiedDate", ComparisonOperator.NotEqual)]
public DateTime? ExcludeModifiedDate { get; set; }
}
public class RangeSearchRequest : IWhereClause
{
// Price range
[ComparativeWhereClause("Price", ComparisonOperator.GreaterThanOrEqual)]
public decimal? MinPrice { get; set; }
[ComparativeWhereClause("Price", ComparisonOperator.LessThanOrEqual)]
public decimal? MaxPrice { get; set; }
// Year range
[ComparativeWhereClause("PublishedYear", ComparisonOperator.GreaterThanOrEqual)]
public int? StartYear { get; set; }
[ComparativeWhereClause("PublishedYear", ComparisonOperator.LessThanOrEqual)]
public int? EndYear { get; set; }
}
SmartWhere supports logical operators to combine multiple conditions.
public class AndSearchRequest : IWhereClause
{
[WhereClause] // Defaults to AND
public string Title { get; set; }
[WhereClause(LogicalOperator.AND)] // Explicit AND
public string Author { get; set; }
}
public class OrSearchRequest : IWhereClause
{
[WhereClause(LogicalOperator.OR)]
public string Title { get; set; }
[WhereClause(LogicalOperator.OR)]
public string Author { get; set; }
[WhereClause(LogicalOperator.OR)]
public string Genre { get; set; }
}
public class MixedSearchRequest : IWhereClause
{
// Title AND Author (AND is default)
[WhereClause]
public string Title { get; set; }
[WhereClause]
public string Author { get; set; }
// Genre OR Publisher (OR)
[WhereClause("Genre", LogicalOperator.OR)]
public string Genre { get; set; }
[WhereClause("Publisher.Name", LogicalOperator.OR)]
public string PublisherName { get; set; }
}
The WhereClauseClass
attribute allows you to organize search properties into separate classes.
public class BookSearchRequest : IWhereClause
{
// Pagination properties
public int Page { get; set; }
public int PageSize { get; set; }
// Search criteria
[WhereClauseClass]
public BookSearchCriteria SearchCriteria { get; set; }
}
public class BookSearchCriteria : IWhereClause
{
[WhereClause]
public string Title { get; set; }
[WhereClause("Author.Name")]
public string AuthorName { get; set; }
[WhereClause("Genre")]
public string Genre { get; set; }
}
public class AdvancedSearchRequest : IWhereClause
{
[WhereClauseClass]
public BasicSearchCriteria Basic { get; set; }
[WhereClauseClass]
public AdvancedSearchCriteria Advanced { get; set; }
}
public class BasicSearchCriteria : IWhereClause
{
[WhereClause]
public string Title { get; set; }
}
public class AdvancedSearchCriteria : IWhereClause
{
[TextualWhereClause(StringMethod.Contains)]
public string Description { get; set; }
[ComparativeWhereClause("Price", ComparisonOperator.GreaterThan)]
public decimal? MinPrice { get; set; }
}
Only include properties that are actually used for filtering:
// ❌ Don't include unused properties
public class InefficientRequest : IWhereClause
{
[WhereClause]
public string Title { get; set; }
[WhereClause]
public string Author { get; set; }
// This property is never used for filtering
public string SortBy { get; set; }
}
// ✅ Only include filter properties
public class EfficientRequest : IWhereClause
{
[WhereClause]
public string Title { get; set; }
[WhereClause]
public string Author { get; set; }
}
Limit the depth of nested properties to improve performance:
// ❌ Deep nesting (may impact performance)
[WhereClause("Publisher.Country.Region.City.Name")]
public string CityName { get; set; }
// ✅ Shallow nesting (better performance)
[WhereClause("Publisher.CityName")]
public string CityName { get; set; }
Use nullable types for optional filters:
public class OptimizedSearchRequest : IWhereClause
{
[WhereClause]
public string Title { get; set; } // Required filter
[WhereClause]
public string? Author { get; set; } // Optional filter
[WhereClause]
public int? PublishedYear { get; set; } // Optional filter
}
// In Program.cs or Startup.cs
services.Configure<SmartWhereOptions>(options =>
{
options.DefaultStringMethod = StringMethod.Contains;
options.CaseSensitive = false;
options.MaxNestingLevel = 10;
options.EnablePerformanceLogging = true;
});
public class CustomizedSearchRequest : IWhereClause
{
[TextualWhereClause(StringMethod.StartsWith, CaseSensitive = true)]
public string Title { get; set; }
[ComparativeWhereClause("Price", ComparisonOperator.GreaterThan, IncludeNullValues = false)]
public decimal? MinPrice { get; set; }
}
// ✅ Consistent naming convention
public class BookSearchRequest : IWhereClause
{
[WhereClause("Title")]
public string BookTitle { get; set; }
[WhereClause("Author.Name")]
public string AuthorName { get; set; }
}
// ✅ Group related properties
public class OrganizedSearchRequest : IWhereClause
{
// Basic search
[WhereClause]
public string Title { get; set; }
// Advanced search
[TextualWhereClause(StringMethod.Contains)]
public string Description { get; set; }
// Numeric filters
[ComparativeWhereClause("Price", ComparisonOperator.GreaterThan)]
public decimal? MinPrice { get; set; }
}
public class SafeSearchRequest : IWhereClause
{
[WhereClause]
public string? Title { get; set; } // Nullable for safety
[WhereClause]
public int? PublishedYear { get; set; } // Nullable for safety
}
Last Updated: 2025-01-16
Version: 2.2.3