Ich nehme an, Sie können eine Unterbedingung aus jeder Zeile in Ihrer GUI erstellen. Zum Beispiel würde die erste Zeile
string userInputName = "john";
Expression<Func<Person, bool>> condition1 = person => person.Name.Contains(userInputName);
ähnlich sein und kann als
var selection = db.Persons.Where(condition1).ToList();
für mehr Unter Bedingungen verwendet werden, and
ist nur eine Verkettung von Where
Bedingungen:
var conditions = new List<Expression<Func<Person, bool>>>() { condition1, condition2, ... };
IQueryable<Person> query = db.Persons;
foreach (var condition in conditions)
{
query = query.Where(condition);
}
var selection = query.ToList();
Der etwas schwierigere Teil kommt mit den or
Bedingungen. Angenommen, Sie haben Ihre Bedingungen in Gruppen von alternativen and
Bedingungen (disjunctive normal form) normalisiert, dann erhalten Sie mehrere Gruppen gültiger Ergebnisse. Aus Gründen der Einfachheit, halte ich es in zwei Gruppen hier, aber es kann auf die gleiche Weise wie die and
Bedingungen verallgemeinert werden:
Die or
kann durch den Union
Betrieb auf Unterabfragen dargestellt werden.
Ein paar letzte Worte: Betrachten Sie stattdessen einige etablierte Filter/Such-Frameworks. Dieser Ansatz ist wahrscheinlich weder der schönste noch der schnellste, den Sie finden können.
Wie gewünscht, ein kleines Beispiel mit einigen In-Memory-Daten. Beachten Sie, dass dies nicht 100% äquivalent zu Linq-to-Entities ist. Zum Beispiel wird der String-Vergleich unterschiedlich mit Groß- und Kleinbuchstaben behandelt, und möglicherweise ist nicht jede Bedingung für SQL erlaubt.
public enum TypeOfContact
{
Unknown,
Email
}
public class Person
{
public string Name { get; set; }
public DateTime Birth { get; set; }
public TypeOfContact ContactType { get; set; }
public string ContactValue { get; set; }
}
public class Program
{
static void Main(string[] args)
{
// test data to simulate a database table
var Persons = new List<Person>
{
// + All conditions met
new Person { Name = "john doe", Birth = new DateTime(2011, 1, 1), ContactType = TypeOfContact.Email, ContactValue = "[email protected]" },
// - Not in result
new Person { Name = "danny doe", Birth = new DateTime(2012, 1, 1), ContactType = TypeOfContact.Email, ContactValue = "[email protected]" },
// + Name contains john
new Person { Name = "john doe", Birth = new DateTime(2013, 1, 1), ContactType = TypeOfContact.Unknown, ContactValue = "" },
// + Birth, ContactType and ContactValue correct
new Person { Name = "justin", Birth = new DateTime(2014, 1, 1), ContactType = TypeOfContact.Email, ContactValue = "[email protected]" },
// - Not in result because Name and Birth are wrong
new Person { Name = "jonny", Birth = new DateTime(1979, 1, 1), ContactType = TypeOfContact.Email, ContactValue = "[email protected]" },
// - Not in result
new Person { Name = "jenny doe", Birth = new DateTime(2016, 1, 1), ContactType = TypeOfContact.Unknown, ContactValue = "" },
}.AsQueryable();
// single-line-conditions
Expression<Func<Person, bool>> c1 = p => p.Name.Contains("john");
Expression<Func<Person, bool>> c2 = p => p.Birth.Date >= new DateTime(1980, 1, 1);
Expression<Func<Person, bool>> c3 = p => p.ContactType == TypeOfContact.Email;
Expression<Func<Person, bool>> c4 = p => p.ContactValue.EndsWith("@email.com");
// DNF groups: outer list = or; inner list = and
// c1 or (c2 and c3 and c4)
var conditionList = new List<List<Expression<Func<Person, bool>>>>
{
new List<Expression<Func<Person, bool>>>
{
c1,
},
new List<Expression<Func<Person, bool>>>
{
c2,
c3,
c4,
},
};
var andSubResults = new List<IQueryable<Person>>();
foreach (var andQueries in conditionList)
{
var subQuery = Persons;
foreach (var andQuery in andQueries)
{
subQuery = subQuery.Where(andQuery);
}
andSubResults.Add(subQuery);
}
var query = andSubResults.FirstOrDefault();
foreach (var subResult in andSubResults.Skip(1))
{
query = query.Union(subResult);
}
var selection = query.ToList();
// just check the result in debugger
}
}
mit Leistung im Verstand für eine erweiterte Suche wie diese, würde ich empfehlen, ein spezielles Produkt verwenden, wie [Elasticsearch] (https://www.elastic.co/), ich Tage damit verbracht, etwas ähnliches im Innern zu tun von EF entdecken nur, wie schlecht es bei größeren Daten funktioniert. – uk2k05
Elasticsearch kann Daten von SQL-Server mit EF abrufen ..... ich habe keine Ahnung. –