ZEXSM / OData.QueryBuilder

OData.QueryBuilder - library for creating complex OData queries (OData version 4.01) based on data models with linq syntax.
MIT License
71 stars 31 forks source link

Supports for complexe string condition in Filter #106

Closed vabic closed 1 year ago

vabic commented 1 year ago

I have a use case for conditional concatenation in Filter.Contains condition.

baseQueryBuilder
               .Filter((item, func, op) =>
               func.Contains(item.Name, searchBy) ||
               func.Contains(func.ComplexConcatExtentionConcat(item), searchBy));
public static string ComplexConcatExtentionConcat(this IOdataFunction func, Item item){
  if (item.Property1) { return func.Concat(item.Name, ("Name"))}
else if(item.Property2) {return func.Concat(item.FullName, ("FullName"))}
}

Cause error Method ComplexConcatExtentionConcat not supported. at OData.QueryBuilder.Expressions.Visitors.ODataExpressionVisitor.VisitExpression(LambdaExpression topExpression, Expression expression). Is there a way to accomplish the condition or work around the error?

ZEXSM commented 1 year ago

Show what item is

vabic commented 1 year ago
using OData.QueryBuilder.Builders;
using OData.QueryBuilder.Conventions.Functions;

public static class ItemDisplayNameFilterExt
{
    public static string ItemDisplayNameFilter(this IODataFunction func, Item item)
    {
        if (item.Unrestricted)
        {
            return func.Concat(item.Name, "(unrestricted)");
        }
        if (item.IntermediateRelease is null)
        {
            return func.Concat(item.Name, $"({item.Year})");
        }

        if (item.IntermediateRelease?.Minor != 0)
        {
            return
                func.Concat(item.Name,
                func.Concat("(",
                func.Concat(item.Year.ToString(),
                func.Concat("IR",
                func.Concat(item.IntermediateRelease?.Major.ToString(),
                func.Concat(".",
                func.Concat(item.IntermediateRelease?.Minor.ToString(), ")")))))));
        }
        if (item.IntermediateRelease.Major != 0)
        {
            return
                func.Concat(item.Name,
                func.Concat("(",
                func.Concat(item.Year.ToString(),
                func.Concat("IR",
                func.Concat(item.IntermediateRelease?.Major.ToString(), ")")))));
        }
        return
                     func.Concat(item.Name,
                     func.Concat("(",
                     func.Concat(item.Year.ToString(), ")")));

    }
}

public class OdatatQueryBuilderExample
{

    public static void Main(string[] args)
    {
        string searchBy = "MyItemName (unrestricted)";
        ODataQueryBuilder _queryBuilder = new("http://api/odata");
        var baseQueryBuilder = _queryBuilder
            .For<Item>("Items")
            .ByList();

        Uri uri = baseQueryBuilder
            .Filter((item, func, op) =>
            func.Contains(item.Name, searchBy) ||
            func.Contains(item.Description, searchBy) ||
            func.Contains(func.ItemDisplayNameFilter(item), searchBy))
            .Count()
            .ToUri();
    }
}

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; } = String.Empty;
    public string Description { get; set; } = String.Empty;

    public Version? IntermediateRelease { get; set; }
    public int Year { get; set; }

    public bool Unrestricted { get; set; }
    // User can search on DisplayName
    public string DisplayName
    {
        get
        {
            if (Unrestricted)
            {
                return $"{Name} (unrestricted)";
            }
            if (IntermediateRelease is null)
            {
                return $"{Name} ({Year})";
            }

            if (IntermediateRelease.Minor != 0)
            {
                return $"{Name} ({Year} IR{IntermediateRelease.Major}.{IntermediateRelease.Minor})";
            }
            else if (IntermediateRelease.Major != 0)
            {
                return $"{Name} ({Year} IR{IntermediateRelease.Major})";
            }
            return $"{Name} ({Year})";
        }
    }
}
vabic commented 1 year ago

I analyzed the problem more, and I tried to generate the ODataQuery manually but it seems that the if-else are not supported. The work around is to make a longer query with all possible concat possibilities