[英]Using LINQ-To-Entities to Generate Information
我正在一個網站上工作,在該網站上,用戶可以將標簽添加到已發布的書本上,就像目前針對Stack Overflow的問題所做的一樣。
課程 :
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
問題
我需要在LINQ中為實體查詢寫一些東西,它根據標簽為我提供數據:
查詢 : bookIds where tagid = 1
返回 : bookid: 113421, 113422
查詢2 : tags 1 and 2
回報 : 113421
我需要標簽及其計數才能顯示在相關標簽中,因此在第一種情況下,我的相關標簽類應具有以下結果。
相關標簽標簽計數2 1 3 1 4 2 8 1
第二種情況 :
RelatedTags
Tag Count
3 1
4 1
如何在LINQ中做到這一點?
只需執行以1:N或1:1關系映射表的外鍵,然后讓設計者為您創建導航屬性。 (Books:BooksTags將1:N從Books.BookID映射到BooksTags.BookID,而BooksTags.TagID則將1:1映射到Tag.TagID)。 這實際上是偽裝的N:M關系。 我不知道設計者是否直接選擇了它,但是通過一些擺弄可以使導航屬性正確。
現在開始提問:
model.Tags.Where(t => t.ID == 1).Books.Select(b => b.ID)
獲取一本書的所有標簽,然后將該表連接到BooksTags上,這樣您就可以簡單地使用Count()來獲取計數。
在第一部分,有趣的限制是,該書必須匹配輸入的每個標簽,因此“ where tagid == someId”的where子句實際上不會起作用。 我設想這樣的事情(LINQ到對象的示例)
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;
它基本上執行從書籍到書簽的連接,也執行到選定標簽ID列表的連接,並將選擇范圍限制為book-> tag匹配的數目等於選定標簽ID的數目。
要拉相關標簽,也許像這樣
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)。
這與答案本身沒有直接關系,但是您可能想看看linqpad,因為它可以幫助您直接從數據庫中構建L2S語句。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.