实体框架,MVC 3,一对多关系

Sni*_*fer 2 entity-framework-4 asp.net-mvc-3

好的 - 先道歉 - 我是一个前端开发人员(HTML,CSS和JS)试图用数据做事 - 从来都不错!

我有一个'Page',可以有一个或多个'系列'.这些"系列"可以包含一个或多个"收藏",这些"收藏"可以与多个"系列"相关联.'Collection'可以包含一个或多个'标题'.这就是我构建数据库的方式:

CREATE TABLE [dbo].[Pages] (
    PageId  INT       NOT NULL PRIMARY KEY, 
    [Title] NCHAR(50) NOT NULL
)

CREATE TABLE [dbo].[Series] (
    [SeriesId] INT        NOT NULL,
    [Title]    NCHAR (50) NOT NULL,
    [PageId]   INT        NOT NULL, 
    PRIMARY KEY CLUSTERED ([SeriesId] ASC), 
    CONSTRAINT [FK_Series_Pages] FOREIGN KEY ([PageId]) REFERENCES [Pages]([PageId])
);

CREATE TABLE [dbo].[Collections] (
    [CollectionId] INT        NOT NULL,
    [Title]        NCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([CollectionId] ASC)
);

CREATE TABLE [dbo].[SeriesCollections] (
    [SeriesCollectionId]   INT    NOT NULL,
    [SeriesId]             INT    NOT NULL, 
    [CollectionId]         INT    NOT NULL, 
    PRIMARY KEY CLUSTERED ([SeriesCollectionId] ASC), 
    CONSTRAINT [FK_SeriesCollections_Series] FOREIGN KEY ([SeriesId]) REFERENCES [Series]([SeriesId]),
    CONSTRAINT [FK_SeriesCollections_Collections] FOREIGN KEY ([CollectionId]) REFERENCES [Collections]([CollectionId])
);

CREATE TABLE [dbo].[Titles] (
    [TitleId]            INT         NOT NULL,
    [Title]              NCHAR (100) NOT NULL,
    [SeriesCollectionId] INT         NOT NULL, 
    PRIMARY KEY CLUSTERED ([TitleId] ASC), 
    CONSTRAINT [FK_Titles_SeriesCollections] FOREIGN KEY ([SeriesCollectionId]) REFERENCES [SeriesCollections]([SeriesCollectionId])
Run Code Online (Sandbox Code Playgroud)

使用实体框架我有以下内容:

public DbSet<Page> Pages { get; set; }
public DbSet<Series> Series { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<SeriesCollection> SeriesCollections { get; set; }
public DbSet<Title> Titles { get; set; }
Run Code Online (Sandbox Code Playgroud)

在视图中我想得到以下内容.

对于给定的'Page'(id),我想要所有'Series'并且在每个'Series'中,能够列出每个'标题'及其相关的'Collection'.

首先 - 我的数据库设置正确吗?其次,我正在努力使用db调用和viewmodels来返回它.

如果有人能帮助那就好了

提前致谢

Sla*_*uma 5

'Collection'可以包含一个或多个'标题'.

因此,我会修改您的数据库表架构:

  • 在表Titles代替[SeriesCollectionId][CollectionId]直接指的对Collections表.

  • 在表中SeriesCollections删除您的PK [SeriesCollectionId]并改为使用剩余的两个字段[SeriesId][CollectionId]复合主键.

  • 现在,你可以模型之间的许多一对多的关系Series,并Collections与EF.然后,连接表SeriesCollections不再是模型的一部分.它只是数据库中隐藏的表,由EF管理.因此你可以删除public DbSet<SeriesCollection> SeriesCollections { get; set; }.

模型类可能如下所示:

public class Page
{
    public int PageId { get; set; }
    [Required]
    [MaxLength(50)]
    pubic string Title { get; set; }
    public ICollection<Series> Series { get; set; }
}

public class Series
{
    public int SeriesId { get; set; }
    [Required]
    [MaxLength(50)]
    pubic string Title { get; set; }
    public int SeriesId { get; set; }
    public int PageId { get; set; } // FK property, helpful but not required
    public Page Page { get; set; }
    public ICollection<Collection> Collections { get; set; }
}

public class Collection
{
    public int CollectionId { get; set; }
    [Required]
    [MaxLength(50)]
    pubic string Title { get; set; }
    public ICollection<Series> Series { get; set; }
    public ICollection<Title> Titles { get; set; }
}

public class Title
{
    public int TitleId { get; set; }
    [Required]
    [MaxLength(100)]
    pubic string TTitle { get; set; } // must be other name then class
    public int CollectionId { get; set; } // FK property
    public Collection Collection { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

对于多对多映射,您需要Fluent API:

public class MyContext : DbContext
{
    public DbSet<Page> Pages { get; set; }
    public DbSet<Series> Series { get; set; }
    public DbSet<Collection> Collections { get; set; }
    public DbSet<Title> Titles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Series>()
            .HasMany(s => s.Collections)
            .WithMany(c => c.Series)
            .Map(a =>
            {
                a.MapLeftKey("SeriesId");
                a.MapRightKey("CollectionId");
                a.ToTable("SeriesCollections");
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信EF会按惯例找出所有其他关系.

对于给定的'Page'(id),我想要所有'Series'并且在每个'Series'中,能够列出每个'标题'及其相关的'Collection'.

使用上面的模型,您可以尝试:

var page = context.Pages.Where(p => p.PageId == id)
    .Include(p => p.Series.Select(s => s.Collections.Select(c => c.Titles)))
    .SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

它将选择包含系列列表的页面,其中包含带有标题列表的集合列表.

不确定这是不是你想要的,只是一个未经测试的起点.

(顺便说一下:你可以先编写你的类(Code-First),然后让EF创建你的数据库表.在设计阶段你想尝试一些映射时更容易,imo.)

编辑

我忘了一件事:如果你真的想要非变量固定长度的字符串字段(NCHAR(50)),你必须在Fluent API中明确地定义它.默认情况下,EF会假设NVARCHAR(50)上面带有映射的字段.设置为固定长度列将如下所示:

modelBuilder.Entity<Page>().Property(p => p.Title).IsFixedLength();
Run Code Online (Sandbox Code Playgroud)