我正在尝试在LINQ中编写查询,到目前为止,我无法使其工作。如果我在历史上设法提出最明显的LINQ问题,那么我道歉但我确实需要一些帮助...
以下是我要做的事情的要点:
我有一个关键字类:
class Keyword
{
public string Name {get; set;}
}
我还有一个文件类:
class File
{
public IList<Keyword> Keywords { get; set;}
}
现在,假设我有一种按关键字搜索文件的方法:
IEnumerable<File> FindByKeywords(IEnumerable<Keyword> keywords)
{
// Let's say that Context.Files is a collection of File objects
// each of which contains a collection of associated keywords
// that may (or may not) match the keywords we get passed as
// a parameter. This is where I need LINQ magic to happen.
return Context.Files; // How do I select the files by the list of keywords?
}
我已经看到在传入的关键字列表中使用Contains的示例,但这似乎只适用于匹配属性是标量的实例。在我的例子中,匹配属性是另一个关键字列表。
换句话说,这不起作用:
IEnumerable<File> FindByKeywords(IEnumerable<Keyword> keywords)
{
return Context.Files.Where(x => keywords.Contains(x);
}
有人有什么想法吗?我真的只需要查找包含一个或多个关键字的文件,这些关键字与作为参数传入的关键字列表中的任何内容相匹配。它可能有一个明显的解决方案,但我看不到它。
提前致谢。
答案 0 :(得分:0)
是否要查找所有File
个对象,Keywords
中的任何元素都存在于您传递给方法的关键字集合中?
在查询中对Keyword
类执行任何操作显然都是禁忌。正如您的错误所示,它只能翻译原始类型。
var names = keywords.Select(x => x.Name).ToList();
return Context.Files.Where(x => keywords.Select(y => y.Name).Intersect(names).Any());
答案 1 :(得分:0)
也许既然你在使用Linq解决这个问题时遇到了麻烦,那么你应该从你可以做的事情开始。例如一些简单的循环。一旦你有了这个工作,你就可以转到Linq查询。
IEnumerable<File> FindByKeywords(IEnumerable<Keyword> keywords)
{
var foundFiles = new List<File>();
foreach (File file in Context.Files)
{
foreach (string fileWord in file)
{
foreach (string keyword in keywords)
{
if (fileWord == keyword)
{
foundFiles.Add(file);
break;
}
}
}
}
return foundFiles;
}
答案 2 :(得分:0)
我可以先建立索引,然后查询索引:
IDictionary<string, List<File>> BuildIndex(IEnumerable<File> files)
{
var index = new Dictionary<string, List<File>>();
foreach (File file in files)
{
foreach (string keyword in file.Keywords.Select(k => k.Name))
{
if (!index.ContainsKey(keyword))
index[keyword] = new List<File>();
index[keyword].Add(file);
}
}
return index;
}
IEnumerable<File> FindByKeywords(IEnumerable<Keyword> keywords)
{
var index = BuildIndex(Context.Files);
return keywords
.Where(k => index.ContainsKey(k.Name))
.SelectMany(k => index[k.Name])
.Distinct()
.ToList();
}
答案 3 :(得分:0)
据我所知,您正在寻找关键词集合中所有关键字的所有文件。
我会这样写:
IEnumerable<File> FilesThatContainsAnyKeyword(
IEnumerable<File> files, // IQueryable<File>?
IEnumerable<Keyword> keywords)
{
var keywordSet = new HashSet<string>(keywords.Select(k => k.Name));
return files.Where(f =>
f.Keywords.Any(k => keywordSet.Contains(k.Name))
);
}
然后叫它:
IEnumerable<File> FindByKeywords(IEnumerable<Keyword> keywords)
{
return FilesThatContainsAnyKeyword(Context.Files, keywords);
}
由于无法直接比较关键字对象的相等性,因此您必须按身份(Name
)对它们进行比较。