映射.NET MVC中具有两个链接表的两个表之间的关系

时间:2013-11-04 04:53:39

标签: sql asp.net-mvc entity-framework

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

想象一下书店数据库。有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

您如何对此进行编码,以便从SectionBooksBestSellers获取数据?我正在使用现有的表,所以这将是数据库优先,但任何其他实现信息可能会有所帮助。

额外信息可能有所帮助。这是一个示例查询,它会在按BestSellerIndex排名的部分中返回所有图书(我将null转换为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

1 个答案:

答案 0 :(得分:1)

通过你的例子,我可以看到你试图用它去哪里。在我看来,这是一个案例,你可能最好通过实体框架的混合方法服务。不同的建模策略(“数据库优先”,“模型优先”,“代码优先”)的命名并不十分明确。例如,即使使用现有数据库,也可以使用Code-First;所有Code-First意味着“模型类”是通过Code而不是设计者定义的。虽然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创建了它管理的类,您无法轻松更改)。