2011-08-23 3 views
2

Ok - d'abord des excuses - Je suis un développeur frontal (HTML, CSS et JS) essayant de faire des choses avec des données - jamais joli!Entity Framework, MVC 3, relation un-à-plusieurs

J'ai une page, qui peut contenir une ou plusieurs séries. Ces 'Séries' peuvent contenir une ou plusieurs 'Collections' et ces 'Collections' peuvent être associées à plus d'une 'Série'. Les 'Collections peuvent contenir un ou plusieurs' Titres '. Voilà comment j'ai structuré mon db:

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]) 

En utilisant Entity Framework, je donne les résultats suivants:

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; } 

l'avis que je veux obtenir ce qui suit.

Pour une 'Page' (id) donnée, je veux que toutes les 'Séries' et dans chacune de ces 'Séries' puissent lister chacun des 'Titres' et leurs 'Collection' associés.

Tout d'abord, mon db est-il correctement configuré? Deuxièmement, je me bats avec l'appel db et viewmodels qui retournerait cela.

Si quelqu'un peut aider ce serait génial

Merci à l'avance

Répondre

5

La Collection de peut contenir un ou plusieurs « titres ».

En raison de cela, je modifierais votre schéma de table DB:

  • Dans le tableau Titles[SeriesCollectionId] par [CollectionId] remplacer, directement au référant tableau Collections. à une clé primaire composite

  • Dans le tableau SeriesCollections retirer votre PK [SeriesCollectionId] et faire à la place les deux autres champs [SeriesId] et [CollectionId]. Vous pouvez maintenant modéliser une relation plusieurs-à-plusieurs entre Series et Collections avec EF. Ensuite, la table de jointure SeriesCollections ne fait plus partie de votre modèle. C'est juste une table cachée dans la DB qui est gérée par EF. Par conséquent, vous pouvez supprimer public DbSet<SeriesCollection> SeriesCollections { get; set; }.

Les classes de modèle pourrait alors ressembler à ceci:

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; } 
} 

Pour beaucoup à plusieurs mapping vous avez besoin API Courant:

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"); 
      }); 
    } 
} 

EF comprendre toutes les autres relations de convention, je crois.

Pour une donnée « Page » (id), je veux tous les « Série » et dans chacun des ces « série », être en mesure d'énumérer chacune des « titres » et son associé « Collection » .

Avec le modèle ci-dessus alors vous pourriez essayer:

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

Il choisirait la page qui contient une liste de série avec une liste des collections avec une liste des titres.

Vous ne savez pas si c'est exactement ce que vous voulez, juste un point de départ non testé.

(BTW: Vous pouvez écrire vos classes de première (Code-First) et laissez EF créer vos tables de base de données Il est plus facile lors de la phase de conception lorsque vous voulez essayer quelques applications, imo..)

Modifier

Une chose que j'ai oubliée: Si vous voulez vraiment des champs de chaîne de longueur fixe non variable (NCHAR(50)), vous devez le définir explicitement dans l'API Fluent. Par défaut, EF supposerait NVARCHAR(50) champs avec le mappage ci-dessus. Le réglage à colonnes de longueur fixe ressemblerait à ceci:

modelBuilder.Entity<Page>().Property(p => p.Title).IsFixedLength(); 
+0

c'est génial et m'a appris beaucoup de choses, ainsi que m'a donné plus de choses à faire et à apprendre! Aimer l'API Fluent. Merci d'avoir pris le temps d'examiner mon problème - c'est très apprécié. – Sniffer

Questions connexes