0

I am fetching the products list whose name starts with numbers, but i would like to apply the two more filters like with specific BranchId and isActive.

Query which returns the list of products whose name starts with numbers.

List<string> searchP = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
.....Where(x=> searchP.Any(y=> x.ProductName.StartsWith(x.ProductName))).ToList();

I have a list of filters in custom FilterCollection object named filters which has three properties, filtername, operatorname and filtervalue.

filters.Add(FilterKey.BranchId, Filteroperator.Equals, 333); same for isActive, this is what I have passed before one layer back.

I would like to get the products whose name starts with number and having BranchId==value in filter and isActive==filter value i.e true / false.

NetMage
  • 26,163
  • 3
  • 34
  • 55
TauFeeQ
  • 153
  • 1
  • 11
  • 1
    "I have a list of filters in custom FilterCollection object named "filters" which has three parameters," the code would tell us much more than a description. Can you please post it? – Mong Zhu Dec 10 '20 at 10:30
  • @MongZhu FilterCollection filters..... ```filter.Add(FilterKey.BranchId, Filteroperator.Equals, 333);``` same for isActive, this is what i have passed before one layer back.. – TauFeeQ Dec 10 '20 at 10:54
  • @MongZhu added. – TauFeeQ Dec 10 '20 at 11:04
  • https://stackoverflow.com/questions/65193835/using-linq-to-find-if-a-text-field-contains-any-string-in-a-list/65200477#65200477 Just replace `Contains` with `StartsWith` – Svyatoslav Danyliv Dec 10 '20 at 11:25
  • @SvyatoslavDanyliv i am getting list or products whose name starts with numbers, but i need to add two more filter which are available in FilterCollections's object. – TauFeeQ Dec 10 '20 at 11:31
  • sorry mate, I don't understand it. `FilterCollection` is this supposed to be something build in in C#? How do you intend to use it? how is it constructed? – Mong Zhu Dec 10 '20 at 12:37
  • Just append a separate `Where` for each member of `filters` in a loop. BTW your sample code is wrong - testing `ProductName.StartsWith(ProductName)` is unlikely to be useful. – NetMage Dec 10 '20 at 19:39
  • You are also going to need to use something like [Dynamic LINQ](https://github.com/StefH/System.Linq.Dynamic.Core) to build convert your `filters` into predicates, or write an `Expression` tree builder. – NetMage Dec 10 '20 at 19:54
  • You need to specify which LINQ you are using: LINQ to SQL / EF 6.x / EF Core 2.0 / 2.1 / 3.x / 5.x and ideally what database driver. My answer assumed LINQ to Objects since LINQ to EF Core 3.x / 5.x doesn't support `localCollection.Any()`. – NetMage Dec 10 '20 at 20:31

2 Answers2

0

If I understand your problem correct IsActiv and BranchId are properties of the Items you are searching.

In this case try something like this:

...Where(x => searchP.Any(y=> x.ProductName.StartsWith(x.ProductName)) 
          && x.IsActive == true/false && x.BranchId == specificVal).ToList();

I would also recommend you check out Regex Patterns instead of your List of startcharacters.

Yamira
  • 15
  • 7
  • But i have values in ```filter[i].FilterValue``` if i tried to write like this ```x.BranchId== filters[0 or 1].FilterValue.FirstOrDefault()).ToList();``` I am getting an exception of ....FilterTuple get_Item(Int32) method and this method cannot be translated into store expression. – TauFeeQ Dec 10 '20 at 10:50
  • I recommend you check out NetMages answer, I assumed a different structur based on your first description. – Yamira Dec 11 '20 at 11:12
0

Given something like:

public enum Filteroperator {
    Equals
}

public class Filter {
    static public Dictionary<Filteroperator, ExpressionType> mapOperator = new() {
        { Filteroperator.Equals, ExpressionType.Equal }
    };

    public string propertyName;
    public Filteroperator op;
    public object value;

    public Filter(string p, Filteroperator o, object v) {
        propertyName = p;
        op = o;
        value = v;
    }

    public Func<T, bool> FilterExpression<T>(IEnumerable<T> _) {
        // p =>
        var parmP = Expression.Parameter(typeof(T), "p");
        // p.{propertyName}
        var propE = Expression.Property(parmP, propertyName);
        var valE = Expression.Constant(value);
        var filterBody = Expression.MakeBinary(Filter.mapOperator[op], propE, valE);
        var filterExpr = Expression.Lambda<Func<T,bool>>(filterBody, parmP);
        return filterExpr.Compile();
    }
}

public class FilterCollection : IList<Filter> {
    // ...
}

You can build your query with:

var q = data.Where(d => searchP.Any(aDigit => d.ProductName.StartsWith(aDigit)));

foreach (var filter in filters)
    q = q.Where(filter.FilterExpression(q));
NetMage
  • 26,163
  • 3
  • 34
  • 55