SmartWhere

🔧 Advanced Features

This page covers the advanced features of SmartWhere, including specialized attributes, logical operators, and performance optimizations.

🔍 TextualWhereClause

The TextualWhereClause attribute provides advanced text search capabilities with multiple string methods.

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'
}

Basic Usage

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; }
}

Case Sensitivity

public class CaseSensitiveSearchRequest : IWhereClause
{
    [TextualWhereClause(StringMethod.Contains, CaseSensitive = true)]
    public string ExactTitle { get; set; }

    [TextualWhereClause(StringMethod.StartsWith, CaseSensitive = false)]
    public string AuthorName { get; set; }
}

⚖️ ComparativeWhereClause

The ComparativeWhereClause attribute enables numeric and date comparisons with various operators.

Comparison Operators

public enum ComparisonOperator
{
    Equal,                  // =
    NotEqual,               // !=
    GreaterThan,            // >
    NotGreaterThan,         // !>
    GreaterThanOrEqual,     // >=
    NotGreaterThanOrEqual,  // !>=
    LessThan,               // <
    NotLessThan,            // !<
    LessThanOrEqual,        // <=
    NotLessThanOrEqual      // !<=
}

Numeric Comparisons

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; }
}

Date Comparisons

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; }
}

Range Queries

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; }
}

🔗 Logical Operators

SmartWhere supports logical operators to combine multiple conditions.

AND Operator (Default)

public class AndSearchRequest : IWhereClause
{
    [WhereClause]  // Defaults to AND
    public string Title { get; set; }

    [WhereClause(LogicalOperator.AND)]  // Explicit AND
    public string Author { get; set; }
}

OR Operator

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; }
}

Mixed Operators

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; }
}

🏗️ WhereClauseClass

The WhereClauseClass attribute allows you to organize search properties into separate classes.

Basic Usage

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; }
}

Nested WhereClauseClass

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; }
}

⚡ Performance Optimizations

1. Property Selection

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; }
}

2. Nested Property Optimization

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; }

3. Null Value Handling

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
}

🔧 Customization Options

Global Configuration

// In Program.cs or Startup.cs
services.Configure<SmartWhereOptions>(options =>
{
    options.DefaultStringMethod = StringMethod.Contains;
    options.CaseSensitive = false;
    options.MaxNestingLevel = 10;
    options.EnablePerformanceLogging = true;
});

Attribute-Level Configuration

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; }
}

🚨 Best Practices

1. Consistent Naming

// ✅ Consistent naming convention
public class BookSearchRequest : IWhereClause
{
    [WhereClause("Title")]
    public string BookTitle { get; set; }

    [WhereClause("Author.Name")]
    public string AuthorName { get; set; }
}

2. Logical Grouping

// ✅ 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; }
}

3. Error Handling

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