По различным причинам я должен иметь возможность разрешить пользователю выбирать элемент из базы данных на основе их выбора столбцов и значений. Например, если у меня есть таблица:LINQ Выбор динамических столбцов и значений
Name | Specialty | Rank
-------+-----------------+-----
John | Basket Weaving | 12
Sally | Basket Weaving | 6
Smith | Fencing | 12
Пользователь может запросить 1, 2 или более столбцов и столбцы, которые они запрашивают могут быть разными. Например, пользователь может запросить записи, где Specialty == Basket Weaving
и Rank == 12. What I do currently is gather the user's request and create a list of
KeyValuePair where the
Key is the column name and the
value` является искомым значением столбца:
class UserSearch
{
private List<KeyValuePair<string, string> criteria = new List<KeyValuePair<string, string>>();
public void AddTerm(string column, string value)
{
criteria.Add(new KeyValuePair<string, string>(column, value);
}
public void Search()
{
using (var db = new MyDbContext())
{
// Search for entries where the column's (key's) value matches
// the KVP's value.
var query = db.MyTable.Where(???);
}
}
}
/* ... Somewhere else in code, user adds terms to their search
* effectively performing the following ... */
UserSearch search = new UserSearch();
search.Add("Specialty", "Basket Weaving");
search.Add("Rank", "12");
Используя этот список KeyValuePair
-х, как я могу наиболее сжато выбирать элементы базы данных, которые соответствовать всем критериям?
using (var db = new MyDbContext)
{
// Where each column name (key) in criteria matches
// the corresponding value in criteria.
var query = db.MyTable.Where(???);
}
EDIT: Я хотел бы использовать EntityFramework вместо raw SQL, если я могу ему помочь.
ОБНОВЛЕНИЕ 3: Я приближаюсь. Я обнаружил способ использовать LINQ, как только я загрузил все значения из таблицы. Это, очевидно, не супер идеально, потому что он загружает все в таблице. Поэтому я думаю, что последним шагом было бы выяснить способ, которым Мне не нужно загружать всю таблицу каждый раз. Вот объяснение того, что я делаю:
Для каждой строки в таблице
db.MyTable.ToList().Where(e => ...
Я составьте список BOOLS представляющих, если столбец соответствует критериям.
criteria.Select(c => e.GetType()?.GetProperty(c.Key)?.GetValue(e)?.ToString() == c.Value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basically just gets the value of specific column
by string
Затем я проверяю, если этот список BOOL все верно
.All(c => c == true)
Пример полного кода ниже:
// This class was generated from the ADO.NET Entity Data Model template
// from the database. I have stripped the excess stuff from it leaving
// only the properties.
public class MyTableEntry
{
public string Name { get; }
public string Specialty { get; }
public string Rank { get; }
}
class UserSearch
{
private List<KeyValuePair<string, string> criteria = new List<KeyValuePair<string, string>>();
public void AddTerm(string column, string value)
{
criteria.Add(new KeyValuePair<string, string>(column, value);
}
public async Task<List<MyTableEntry>> Search()
{
using (var db = new MyDbContext())
{
var entries = await db.MyTable.ToListAsync();
var matches = entries.Where(e => criteria.Select(c => e.GetType()
?.GetProperty(c.Key)
?.GetValue(e)
?.ToString() == c.Value)
.All(c => c == true));
return matches.ToList();
}
}
}
Кажется, моя проблема заключается в этот сегмент кода:
e.GetType()?.GetProperty(c.Key)?.GetValue(e)?.ToString()
Я не знаком с деревьями выражений, поэтому, возможно, в них лежит ответ. Я также могу попробовать Dynamic LINQ.
Я думаю, что это сообщение поможет, http://stackoverflow.com/questions/821365/how-to-convert-a-string-to-its-equivalent-expression-tree Вам нужно будет преобразовать строку, которую вы хотите в Where на фактическое выражение, которое будет работать. – Dylan
Я обновил свой ответ, чтобы включить сгенерированный SQL из linq, чтобы облегчить проблемы, которые вы делаете ненужными сравнениями в SQL. – Jakotheshadows
У вас еще не решили? –