【发布时间】:2016-02-10 05:39:11
【问题描述】:
出于各种原因,我需要能够允许用户根据他们对列和值的选择从数据库中选择一个项目。例如,如果我有一张桌子:
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 ofKeyValuePairwhere theKeyis the column name and theValue` 是列的所需值:
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(???);
}
编辑:如果可以的话,我想使用 EntityFramework 而不是原始 SQL。
更新 3:我越来越近了。下载后,我发现了一种使用 LINQ 的方法 表中的所有值。这显然不是超级理想,因为它下载 表中的所有内容。所以我想最后一步是找出一种方法 我不必每次都下载整个表格。这是我在做什么的解释:
对于表中的每一行
db.MyTable.ToList().Where(e => ...
我制作了一个布尔列表,表示该列是否符合条件。
criteria.Select(c => e.GetType()?.GetProperty(c.Key)?.GetValue(e)?.ToString() == c.Value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basically just gets the value of specific column
by string
然后我检查这个布尔列表是否都是真的
.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()
我不熟悉表达式树,所以答案可能就在它们之中。我也可以试试动态 LINQ。
【问题讨论】:
-
我认为这篇文章会有所帮助,stackoverflow.com/questions/821365/… 您必须将 Where 中所需的字符串转换为有效的实际表达式。
-
我已经更新了我的答案以包括从 linq 生成的 SQL,以减轻您在 SQL 中进行不必要的比较的担忧。
-
你解决了吗?
标签: c# wpf entity-framework linq