C# Linq到加入集合和筛选的对象
我在使用Linq to对象过滤/连接内存中的对象列表时遇到问题,通常是一个简单的SQL查询 场景:C# Linq到加入集合和筛选的对象,c#,linq,entity-framework,linq-to-objects,C#,Linq,Entity Framework,Linq To Objects,我在使用Linq to对象过滤/连接内存中的对象列表时遇到问题,通常是一个简单的SQL查询 场景: 拥有json服务(.asmx)允许客户端通过实体框架包装的存储过程(函数导入)进行DB调用。在本例中,[Web方法]“GetArticles(int[]TagIds)” 我现在希望缓存这些数据以保存DB调用,并对缓存的集合应用过滤器 数据: 与2个实体的多对多关系:文章、标签 文章可以有许多标记,并且标记可以与许多文章关联(因此额外的链接表'ArticlesTags') web服务筛选器参数将
拥有json服务(.asmx)允许客户端通过实体框架包装的存储过程(函数导入)进行DB调用。在本例中,[Web方法]“GetArticles(int[]TagIds)”
我现在希望缓存这些数据以保存DB调用,并对缓存的集合应用过滤器 数据:
- 与2个实体的多对多关系:文章、标签
- 文章可以有许多标记,并且标记可以与许多文章关联(因此额外的链接表'ArticlesTags')
SELECT DISTINCT a.*
FROM Article a INNER JOIN ArticlesTags at ON a.ArticleId = at.ArticleId
WHERE at.TagId in (0, 1.. 'list of tag ids')
我遇到了很多障碍-EF包装的存储过程不允许SQL 2008(表值参数),因此我无法以首选格式传入TagId列表筛选器。 我发现了一个示例,其中一个存储过程调用可以返回两个结果集,这可能会解决这个问题。 因此,一旦我有了要缓存的两个集合(Articles和ArticleStag),如何使用linq to对象连接并随后基于可能的TagId的filter参数进行过滤?以下是一种在linq中“重写”SQL查询的方法:
class Article {
public int ArticleId;
public string ArticleName;
// Other fields...
}
class ArticleComparer : IEqualityComparer<Article> {
public bool Equals(Article x, Article y) {
return x.ArticleId == y.ArticleId && x.ArticleName == y.ArticleName;
}
public int GetHashCode(Article obj) {
return obj.ArticleId.GetHashCode();
}
}
class ArticlesTag {
public int TagId;
public int ArticleId;
// Other fields...
}
class Program {
static void Main(string[] args) {
// Test data:
var articles = new[] {
new Article { ArticleId = 1, ArticleName = "Article A" },
new Article { ArticleId = 2, ArticleName = "Article B" },
new Article { ArticleId = 3, ArticleName = "Article C" }
};
var article_tags = new[] {
new ArticlesTag { TagId = 1, ArticleId = 1 },
new ArticlesTag { TagId = 2, ArticleId = 1 },
new ArticlesTag { TagId = 3, ArticleId = 1 },
new ArticlesTag { TagId = 4, ArticleId = 2 },
new ArticlesTag { TagId = 5, ArticleId = 2 },
new ArticlesTag { TagId = 6, ArticleId = 3 },
new ArticlesTag { TagId = 7, ArticleId = 3 }
};
var tag_ids = new HashSet<int>(new[] { 2, 3, 6 });
// JOIN "query":
var q = (
from article in articles
join article_tag in article_tags
on article.ArticleId equals article_tag.ArticleId
where tag_ids.Contains(article_tag.TagId)
select article
).Distinct(new ArticleComparer());
foreach (var article in q)
Console.WriteLine(
string.Format(
"ArticleId = {0}\tArticleName = {1}",
article.ArticleId,
article.ArticleName
)
);
}
}
因此,您有一个Article表、一个Tags表和一个ArticleTags表,该表将Articles ID与一个Tags ID关联起来。然后遍历ArticleTags并获取与该articles ID匹配的所有TagID,然后遍历标记以获取与该标记ID相关联的名称。将其转换为一个整洁的字典,其中包含一个键标记名,该值是标记名的IEnumerable
var articleDictionary = articles.ToDictionary(
a => a.Name, // article name is key
a => ArticleTags
.where(t => t.ArticleID == a.Id)
.select(t => Tags.Single(tag => tag.id == t.id).TagName // value is an IEnumerable<string> of tag names
)
foreach (var article in articleDictionary)
{
Console.WriteLine(article.Key);
foreach (var tag in article.Value)
{
Console.WriteLine("\t" + tag)
}
}
var articleDictionary = articles.ToDictionary(
a => a.Name, // article name is key
a => ArticleTags
.where(t => t.ArticleID == a.Id)
.select(t => Tags.Single(tag => tag.id == t.id).TagName // value is an IEnumerable<string> of tag names
)
foreach (var article in articleDictionary)
{
Console.WriteLine(article.Key);
foreach (var tag in article.Value)
{
Console.WriteLine("\t" + tag)
}
}
var articleDictionary = articles.ToDictionary(
a => a,
a => ArticleTags
.where(t => t.ArticleID == a.Id)
.select(t => Tags.Single(tag => tag.id == t.id)
)