I am trying to link multiple values OR in a loop with LINQ.
Situation
Plattform: .net 5
C# 9
We are building a filter logic for a list. In the current case it concerns string values which are to be filtered.
The user can search for one or more values. He can decide if the single search terms are AND/OR linked and if a value is negated.
I saw this entry. But since my values are in the loop, I can't use ||
.
https://stackoverflow.com/a/37195788/1847143
Example:
- All animals with "A" in the name
SELECT * FROM "Animal" WHERE "Name" = 'A';
- All animals with "A" or "B" in the name
SELECT * FROM "Animal" WHERE "Name" = 'A' OR "Name" = 'B';
- All animals with "A" or "B" or NOT "C" in the name (This would be a meaningless search)
SELECT * FROM "Animal" WHERE "Name" = 'A' OR "Name" = 'B' OR "Name" != 'C' ;
- All animals with "A" and "B" in the name
SELECT * FROM "Animal" WHERE "Name" = 'A' AND "Name" = 'B';
- All animals with "A" and "B" and NOT "C" in the name
SELECT * FROM "Animal" WHERE "Name" = 'A' AND "Name" = 'B' AND "Name" != 'C';
Problem
The AND link with LINQ is no problem. But how can the values be linked with OR?
Code Example
using System.Collections.Generic;
using System.Linq;
namespace SampleProject
{
public class Program
{
public static void Main(string[] args)
{
// Or Condtion
Condition condition = Condition.Or;
var animalsQuery = Animals.AsQueryable();
// Loop over all search values to extend the query
foreach (FilterValue filterValue in FilterValues)
{
switch (filterValue.LikeType)
{
case LikeType.Left: // LIKE '%value'
animalsQuery = filterValue.IsNegated
? animalsQuery.Where(animal => !animal.Name.EndsWith(filterValue.Value))
: animalsQuery.Where(animal => animal.Name.EndsWith(filterValue.Value));
break;
case LikeType.Right: // LIKE 'value%'
animalsQuery = filterValue.IsNegated
? animalsQuery.Where(animal => !animal.Name.StartsWith(filterValue.Value))
: animalsQuery.Where(animal => animal.Name.StartsWith(filterValue.Value));
break;
case LikeType.LeftAndRight: // LIKE '%value%'
animalsQuery = filterValue.IsNegated
? animalsQuery.Where(animal => !animal.Name.Contains(filterValue.Value))
: animalsQuery.Where(animal => animal.Name.Contains(filterValue.Value));
break;
case LikeType.Equals: // Like 'value'
animalsQuery = filterValue.IsNegated
? animalsQuery.Where(animal => animal.Name != filterValue.Value)
: animalsQuery.Where(animal => animal.Name == filterValue.Value);
break;
}
}
var result = animalsQuery.ToList();
}
/// Values to filter
public static List<Animal> Animals = new()
{
new() {Name = "Lenny"},
new() {Name = "Gideon"},
new() {Name = "Shania"},
new() {Name = "Jada"},
new() {Name = "Kamil"},
new() {Name = "Fariha"},
};
/// Search Values
public static List<FilterValue> FilterValues = new()
{
new() {Value = "a", LikeType = LikeType.Left},
new() {Value = "n", LikeType = LikeType.Right},
new() {Value = "f", LikeType = LikeType.LeftAndRight},
new() {Value = "k", LikeType = LikeType.Equals},
};
}
public class Animal
{
public string Name { get; set; }
}
public class FilterValue
{
public string Value { get; set; }
public bool IsNegated { get; set; }
public LikeType LikeType { get; set; }
}
public enum LikeType
{
Left = 1,
Right = 2,
LeftAndRight = 3,
Equals = 4,
}
public enum Condition
{
And = 1,
Or = 2,
}
}