Leider LINQ to Entities unterstützt derzeit keine verbindet sich zu inmemory Sammlung, noch Contains
für nicht primitive inmemory Sammlung. Der einzige Weg, den ich sehe (tatsächlich gibt es einen anderen, der hier beschrieben wird Entity Framework LINQ Get all items part of another collection, aber jetzt denke ich, dass dies geeigneter ist), ist OR
Filter mit einigen Ausdruck Build Helper zu konstruieren.
Zum Beispiel mit der PredicateUtils
Klasse von Establish a link between two lists in linq to entities where clause, könnte es so aussehen:
Zuerst eine wenig Hilfsmethode
static Expression<Func<PropertyDetail, bool>> LocationFilter(string value, int index)
{
if (!string.IsNullOrEmpty(value))
{
if (index == 0) return d => d.Continent == value;
if (index == 1) return d => d.Country == value;
if (index == 2) return d => d.State == value;
}
return null;
}
hinzufügen und dann
var locationsFilter = locations.Select(location => location.Select(LocationFilter)
.Aggregate(PredicateUtils.And)).Aggregate(PredicateUtils.Or);
if (locationsFilter != null)
query = query.Where(locationsFilter);
Für Vollständigkeit verwenden Hier ist die verwendete Hilfsklasse:
public static class PredicateUtils
{
sealed class Predicate<T>
{
public static readonly Expression<Func<T, bool>> True = item => true;
public static readonly Expression<Func<T, bool>> False = item => false;
}
public static Expression<Func<T, bool>> Null<T>() { return null; }
public static Expression<Func<T, bool>> True<T>() { return Predicate<T>.True; }
public static Expression<Func<T, bool>> False<T>() { return Predicate<T>.False; }
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
if (Equals(left, right)) return left;
if (left == null || Equals(left, True<T>())) return right;
if (right == null || Equals(right, True<T>())) return left;
if (Equals(left, False<T>()) || Equals(right, False<T>())) return False<T>();
var body = Expression.AndAlso(left.Body, right.Body.Replace(right.Parameters[0], left.Parameters[0]));
return Expression.Lambda<Func<T, bool>>(body, left.Parameters);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
if (Equals(left, right)) return left;
if (left == null || Equals(left, False<T>())) return right;
if (right == null || Equals(right, False<T>())) return left;
if (Equals(left, True<T>()) || Equals(right, True<T>())) return True<T>();
var body = Expression.OrElse(left.Body, right.Body.Replace(right.Parameters[0], left.Parameters[0]));
return Expression.Lambda<Func<T, bool>>(body, left.Parameters);
}
static Expression Replace(this Expression expression, Expression source, Expression target)
{
return new ExpressionReplacer { Source = source, Target = target }.Visit(expression);
}
class ExpressionReplacer : ExpressionVisitor
{
public Expression Source;
public Expression Target;
public override Expression Visit(Expression node)
{
return node == Source ? Target : base.Visit(node);
}
}
}
UPDATE: Wie in den Kommentaren aufgefordert, hier ist die Lösung für locations
List<Location>
sein:
var locationsFilter = locations.Select(location =>
{
var filter = PredicateUtils.Null<PropertyDetail>();
if (!string.IsNullOrEmpty(location.Continent))
filter = filter.And(d => d.Continent == location.Continent);
if (!string.IsNullOrEmpty(location.Country))
filter = filter.And(d => d.Country == location.Country);
if (!string.IsNullOrEmpty(location.State))
filter = filter.And(d => d.State == location.State);
return filter;
}).Aggregate(PredicateUtils.Or);
Danke Ivan, das scheint zu funktionieren (ich habe buchstäblich Stunden damit verbracht, damit zu kämpfen und das ist die erste Lösung, die funktioniert hat). Es ist jedoch möglich, dies mit einer neuen Liste() zu arbeiten, da es viel einfacher wäre, diese Liste aufzubauen, anstatt ein mehrdimensionales Array zu verwenden, wie zum Beispiel: var locations = new [] –
@MarkAtkins Bitte schön. Und ja, es ist möglich, siehe das Update. –
Danke Ivan, du hast mein schwieriges Problem gelöst. Ich denke nicht, dass ich mir das selbst leicht ausgedacht hätte. Du bist ein Star :) –