我是在一个网站上的用户可以添加标签到他们张贴的书籍,很像目前做的问题堆栈溢出。
类
Books
{
bookId,
Title
}
Tags
{
Id
Tag
}
BooksTags
{
Id
BookId
TagId
}这是很少的样本记录。
Books
BookId Title
113421 A
113422 B
Tags
Id Tag
1 ASP
2 C#
3 CSS
4 VB
5 VB.NET
6 PHP
7 java
8 pascal
BooksTags
Id BookId TagId
1 113421 1
2 113421 2
3 113421 3
4 113421 4
5 113422 1
6 113422 4
7 113422 8问题
bookIds where tagid = 1
返回:bookid: 113421, 113422
查询2:tags 1 and 2
返回:113421第二例
RelatedTags
Tag Count
3 1
4 1在LINQ里我该怎么做?
发布于 2010-05-20 20:20:04
在第一部分中,有趣的限制是,书中必须匹配输入的每个标记,因此"where tagid == someId“的where子句将无法真正工作。我设想像这样的东西(示例)
List<int> selectedTagIds = new List<int>() { 1, 2 };
var query = from book in books
join booktag in booktags
on book.Id equals booktag.BookId
join selectedId in selectedTagIds
on booktag.TagId equals selectedId
group book by book into bookgroup
where bookgroup.Count() == selectedTagIds.Count
select bookgroup.Key;它基本上执行一个连接,从图书到书签,也到选择的标签ids列表,并将选择限制在与book->标记匹配的计数等于所选标记ids的计数的位置。
拉出相关的标签,也许是这样的
var relatedTags = from book in query // use original query as base
join booktag in booktags
on book.Id equals booktag.BookId
join tag in tags
on booktag.TagId equals tag.Id
where !selectedTagIds.Contains(tag.Id) // exclude selected tags from related tags
group tag by tag into taggroup
select new
{
Tag = taggroup.Key,
Count = taggroup.Count()
};快速示例的完整代码。不完全是这样,但你知道这个主意。
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackOverflow
{
class Program
{
static void Main()
{
List<Book> books = new List<Book>()
{
new Book() { Id = 113421, Title = "A" },
new Book() { Id = 113422, Title = "B" }
};
List<Tag> tags = new List<Tag>()
{
new Tag() { Id = 1, Name = "ASP" },
new Tag() { Id = 2, Name = "C#" },
new Tag() { Id = 3, Name = "CSS" },
new Tag() { Id = 4, Name = "VB" },
new Tag() { Id = 5, Name = "VB.NET" },
new Tag() { Id = 6, Name = "PHP" },
new Tag() { Id = 7, Name = "Java" },
new Tag() { Id = 8, Name = "Pascal" }
};
List<BookTag> booktags = new List<BookTag>()
{
new BookTag() { Id = 1, BookId = 113421, TagId = 1 },
new BookTag() { Id = 2, BookId = 113421, TagId = 2 },
new BookTag() { Id = 3, BookId = 113421, TagId = 3 },
new BookTag() { Id = 4, BookId = 113421, TagId = 4 },
new BookTag() { Id = 5, BookId = 113422, TagId = 1 },
new BookTag() { Id = 6, BookId = 113422, TagId = 4 },
new BookTag() { Id = 7, BookId = 113422, TagId = 8 }
};
List<int> selectedTagIds = new List<int>() { 1,2 };
// get applicable books based on selected tags
var query = from book in books
join booktag in booktags
on book.Id equals booktag.BookId
join selectedId in selectedTagIds
on booktag.TagId equals selectedId
group book by book into bookgroup
where bookgroup.Count() == selectedTagIds.Count
select bookgroup.Key;
foreach (Book book in query)
{
Console.WriteLine("{0}\t{1}",
book.Id,
book.Title);
}
// get related tags for selected tags
var relatedTags = from book in query // use original query as base
join booktag in booktags
on book.Id equals booktag.BookId
join tag in tags
on booktag.TagId equals tag.Id
where !selectedTagIds.Contains(tag.Id) // exclude selected tags from related tags
group tag by tag into taggroup
select new
{
Tag = taggroup.Key,
Count = taggroup.Count()
};
foreach (var relatedTag in relatedTags)
{
Console.WriteLine("{0}\t{1}\t{2}",
relatedTag.Tag.Id,
relatedTag.Tag.Name,
relatedTag.Count);
}
Console.Read();
}
}
class Book
{
public int Id { get; set; }
public string Title { get; set; }
}
class Tag
{
public int Id { get; set; }
public string Name { get; set; }
}
class BookTag
{
public int Id { get; set; }
public int BookId { get; set; }
public int TagId { get; set; }
}
}因此,对于选定的标签1和2,您将得到图书A,相关的标签将是3 (CSS)和4 (VB)。
发布于 2010-05-20 20:00:57
只需执行外键映射1:N或1:1关系中的表,然后让设计人员为您创建导航属性。(书籍:BooksTags将1:N从Books.BookID映射到BooksTags.BookID,BooksTags.TagID映射1:1到Tags.TagID)。这实际上是一个变相的N:M关系。我不知道设计人员是否直接发现了这一点,但是通过一些修改,您可以获得正确的导航属性。
现在请回答以下问题:
model.Tags.Where(t => t.ID == 1).Books.Select(b => b.ID)发布于 2010-05-21 03:47:08
这与答案本身没有直接关系,但是您可能想看看衬垫,因为它将帮助您直接从数据库构建L2S语句。
https://stackoverflow.com/questions/2877202
复制相似问题