I am trying following to use in & and with in a same query for Entity Framework Core
// http://www.albahari.com/nutshell/predicatebuilder.aspx
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
I am trying scenario like
select *
from transaction
where channel = 1
and msisdn = '123123123'
and service in (1, 2, 3)
or
select *
from transaction
where channel = 1
and msisdn = '123123123'
and (service = 1 or service = 2 or service = 3)
private static Expression<Func<Transaction, bool>> CreateSearchPredicate(TransactionSearchQuery search, User user)
{
var predicate = PredicateBuilder.True<Transaction>();
if (search.fk_channel_id > 0)
{
predicate = predicate.And(p => p.fk_channel_id == search.fk_channel_id);
}
// msisdn
if (!string.IsNullOrWhiteSpace(search.msisdn))
{
predicate = predicate.And(p => p.msisdn == search.msisdn);
}
if (search.transactionStates != null && search.transactionStates.Count > 0)
{
var predicateX = PredicateBuilder.True<Transaction>();//also tried with False
foreach (var val in search.transactionStates)
{
predicateX = predicateX.Or(p => p.statusid == val);
}
predicate = predicate.And(predicateX);
}
return predicate;
}
Please help me out - what changes do I need in my CreateSearchPredicate
to run And & In (or clues simultaneously)
My db is mysql My code in repository is like
public override IEnumerable<Transaction> GetAll(Expression<Func<Transaction, bool>> predicate)
{
return _context.Set<Transaction>().Include(h => h.ServiceOwner).Include(h => h.TransactionState).Include(h => h.OriginationValidationState).Include(h => h.CommunicationChannel).ThenInclude(h => h.Channel).Where(predicate).AsEnumerable();
//return _context.Set<Transaction>().Where(predicate).AsEnumerable();
}
Don't know my solution is correct or not but i have use contains clause of list to resolve it within And predicate like following
if (search.transactionStates != null && search.transactionStates.Count > 0)
{
predicate = predicate.And(p => search.transactionStates.Contains(p.statusid));
}
if (search.services != null && search.services.Count > 0)
{
predicate = predicate.And(p => p.fk_authentication_service_id.HasValue && search.services.Contains(p.fk_authentication_service_id.Value));
}
if (search.channels != null && search.channels.Count > 0)
{
predicate = predicate.And(p => p.fk_channel_id.HasValue && search.channels.Contains(p.fk_channel_id.Value));
}