1

我试图弄清楚是否可以在由两个链接表链接的两个表之间建立实体关系。我不确定这是否可能。

想象一个书店数据库。有Books而且有Sections桌子。这些表通过称为SectionBooks(多对多,因为一本书可能在多个部分中)的链接表连接。但是商店中的每个部分都会有一个畅销书列表,这是该部分的畅销书的非详尽排名。这将在BestSellers.

数据可能如下所示:

[Books]
BookId  Title           Author
1000    Allegiant       Roth
1001    The Book Thief  Zusak
1002    Mocking Jay     Collins
1003    Fan Girl        Rowell
1004    I am Malala     Yousafzai

[Sections]
SectionId Name
1  Fiction
2  Young Adult

[SectionBooks]
SectionId  BookId
2          1000
2          1001
2          1002
2          1003
2          1004

[BestSellers]
SectionId  BookId  BestSellerIndex
2          1000    1
2          1001    2
2          1002    3

您将如何编写代码以便可以从SectionBooks和获取数据BestSellers?我正在使用现有表执行此操作,因此这将是数据库优先的,但任何其他实现信息可能会有所帮助。

额外的信息可能会有所帮助。这是一个示例查询,它将返回按其排名的部分中的所有书籍BestSellerIndex(我将nulls 转换为999以便排名更明显。)

SELECT 
    ISNULL(BestSellerIndex, 999) AS BestSellerIndex
    SectionBooks.SectionId,
    Books.Id, Books.Title, Books.Author
FROM Books
INNER JOIN SectionBooks ON Books.BookId = SectionBooks.BookId
LEFT OUTER JOIN BestSellers BestSellers ON Book.BookId = BestSellers.BookId
WHERE SectionBooks.SectionId = 2 AND (BestSellers.SectionId = 2 OR BestSellers.SectionId IS NULL)  
ORDER BY BestSellerIndex, Title DESC

这将产生以下数据集:

BestSellerIndex  SectionId  BookId  Title           Author
0                2          1000    Allegiant       Roth
1                2          1001    The Book Thief  Zusak
2                2          1002    Mocking Jay     Collins
999              2          1003    Fan Girl        Rowell
999              2          1004    I am Malala     Yousafzai
4

1 回答 1

1

通读您的示例,我可以看到您要解决的问题。在我看来,在这种情况下,您可能最好使用 Entity Framework 的混合方法。不同的建模策略(“数据库优先”、“模型优先”、“代码优先”)没有很清楚地命名。例如,您可以使用 Code-First,即使是现有的数据库;所有代码优先意味着“模型类”是通过代码定义的,而不是设计者。虽然 Code-First 可以创建数据库,但它与现有数据库一起工作得很好,因此是“混合方法”。

使用 Code-First 和少量 Fluent API 可以更简单地简化此领域模型。

使用 Code-First 建模,您的模型非常简单:

public class Book()
{
    public int BookId {get;set;}
    public string Title {get;set;}
    public string Author {get;set;}

    public virtual ICollection<Section> Sections {get;set;}
} 

public class Section()
{
    public int SectionId {get;set;}
    public string Name {get;set;}

    public virtual ICollection<Book> Books {get;set;}
}

public class BestSeller()
{
    public int BestSellerIndex {get;set;}

    public Section Section {get;set;}
    public Section Book {get;set;}
}

然后你使用一些 Fluent API 来确保表格以正确的方式映射,例如......

// Define the BestSeller to have a composite key from the 2 joined tables
modelBuilder.Entity<BestSeller>().HasKey(t => 
                                  new {t.Section.SectionId, t.Book.BookId});

// Define the Many to Many mapping
modelBuilder.Entity<Book>()
                           .HasMany(b => b.Section)
                           .WithMany(s => s.Book)
                           .Map(
                            m => {
                                  m.MapLeftKey("BookId");
                                  m.MapRightKey("SectionId");
                                  m.ToTable("SectionBooks");
                            });

您可能需要其他 Fluent API 来确保表名是复数形式,并且表模式匹配,更多信息请参见 MSDN

从这里,您可以简单地枚举集合......即

bestSellers = context.BestSellers();
foreach (var bestSeller in bestSellers)
{
      var title = bestSeller.Book.Title;
      var section = bestSeller.Section.Name;

      ...
}

这可能会进一步优化或调整,您可以通过使用 Database-First 模型设计器来获得相同的结果,但我不熟悉那里的所有选项,这种方法可以让您更精确地控制最终结果(因为 Database-First Designer 创建了它管理的类,您无法轻易更改)。

于 2013-11-04T06:27:01.563 回答