2012-07-08 9 views
59

Z przykładów, które widziałem w Internecie oraz w książce Kodowanie pierwiastków w programie Entity Framework, jeśli masz kolekcję na obu klasach EF, utworzysz tabelę mapowania, taką jak MembersRecipes i klucz podstawowy z każdej klasy łączyłoby się z tą tabelą.Tablica odwzorowań wielu do wielu

Jednak gdy wykonuję poniższe czynności, otrzymuję nowe pole w tabeli Recipes o nazwie Member_Id i Recipe_Id w tabeli Members.

Który tworzy tylko dwa relacje jeden do wielu, ale nie wielu do wielu, więc mógłbym mieć Członka 3 połączonego z Przepisami (4,5,6) i Przepis 4 połączonymi z Członkami (1,2, 3) itp.

Czy istnieje sposób utworzenia tego odwzorowania? a jeśli tak, to jak nazwać to coś innego, na przykład "książki kucharskie"?

Dzięki

public abstract class Entity { 
     [Required] 
     public int Id { get; set; } 
    } 

    public class Member : Entity { 
     [Required] 
     public string Name { get; set; } 

     public virtual IList<Recipe> Recipes { get; set; } 
    } 

    public class Recipe : Entity { 
     [Required] 
     public string Name { get; set; } 

     [ForeignKey("Author")] 
     public int AuthorId { get; set; } 
     public virtual Member Author { get; set; } 

      .... 

     public virtual IList<Member> Members { get; set; } 
    } 

UPDATE: Poniżej jest inne podejście Próbowałem który nie korzysta z Fluent API i zastępuje AuthorId & Author na Recipe z flagą właściciela, mam również przemianowany poniżej przykład z Cookbooks do MembersRecipes, to również rozwiązuje mój problem podobny do odpowiedzi, ale jak wspomniano, ma dalsze konsekwencje.

public class MembersRecipes { 

    [Key, Column(Order = 0)] 
    [ForeignKey("Recipe")] 
    public int RecipeId { get; set; } 
    public virtual Recipe Recipe { get; set; } 

    [Key, Column(Order = 1)] 
    [ForeignKey("Member")] 
    public int MemberId { get; set; } 
    public virtual Member Member { get; set; } 

    public bool Owner { get; set; } 
} 

aw Recipe & Member klas I zmienił kolekcje

public virtual IList<MembersRecipes> MembersRecipes { get; set; } 
+2

dotycząceTwojego zaktualizowania w żargonie Entity Framework, że wiele-do-wielu podejście zwane * wiele-do-wielu mapowania z ładunku * I nie wiem, dlaczego wymyślili bardzo wymyślny termin (ładunek); lub tylko ja, moim ojczystym językiem nie jest angielski :-) Zazwyczaj kojarzę słowo "ładunek" z wirusem komputerowym. W EF, ładunek nie jest czymś złowrogim, możesz zabezpieczyć swój projekt w przyszłości, ustawiając tabelę w encję gotową na ładunek (np. Poprzez dodanie dodatkowego identyfikatora jako klucza podstawowego, w konsekwencji musisz przekonwertować istniejące wiele-do-wielu złożonych pk na unikalne kolumny kompozytowe) z get-go –

+1

W twoim przypadku nie dodałeś dodatkowego identyfikatora, utrzymałeś złożony klucz podstawowy. Flaga właściciela na stole to ładunek. –

+0

@ MichaelBuen Ładunek to tabela odwzorowania (relacja), w której można umieścić dodatkowe dane (np. Datę utworzenia relacji) w. Jeśli powinieneś używać funkcji wiele-do-wielu z ukrytą tabelą, nie możesz dodać ładunku do relacji – RHAD

Odpowiedz

95

Czyńcie to na DbContext OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{  
    modelBuilder.Entity<Recipe>() 
     .HasMany(x => x.Members) 
     .WithMany(x => x.Recipes) 
    .Map(x => 
    { 
     x.ToTable("Cookbooks"); // third table is named Cookbooks 
     x.MapLeftKey("RecipeId"); 
     x.MapRightKey("MemberId"); 
    }); 
} 

Można zrobić to na odwrót też, że to to samo, tylko druga strona tej samej monety:

modelBuilder.Entity<Member>() 
    .HasMany(x => x.Recipes) 
    .WithMany(x => x.Members) 
.Map(x => 
{ 
    x.ToTable("Cookbooks"); // third table is named Cookbooks 
    x.MapLeftKey("MemberId"); 
    x.MapRightKey("RecipeId"); 
}); 

Dalsze przykłady:

http://www.ienablemuch.com/2011/07/using-checkbox-list-on-aspnet-mvc-with_16.html

http://www.ienablemuch.com/2011/07/nhibernate-equivalent-of-entity.html


UPDATE

Aby zapobiec cykliczne odwołanie na własność autor, oprócz powyżej, trzeba dodać to:

modelBuilder.Entity<Recipe>() 
    .HasRequired(x => x.Author) 
    .WithMany() 
    .WillCascadeOnDelete(false); 

Idea pozyskiwane tutaj: EF Code First with many to many self referencing relationship

Rdzeń rzeczą jest, trzeba poinformować EF że nieruchomość Autor (który jest instancją państwo) nie posiada zbiory receptur (oznaczony przez WithMany()); w ten sposób cykliczne odniesienie może zostać zatrzymane na właściwości Autor.

Są tworzone tabele od pierwszego kodeksu odwzorowań powyżej:

CREATE TABLE Members(
    Id int IDENTITY(1,1) NOT NULL primary key, 
    Name nvarchar(128) NOT NULL 
); 


CREATE TABLE Recipes(
    Id int IDENTITY(1,1) NOT NULL primary key, 
    Name nvarchar(128) NOT NULL, 
    AuthorId int NOT NULL references Members(Id) 
); 


CREATE TABLE Cookbooks(
    RecipeId int NOT NULL, 
    MemberId int NOT NULL, 
    constraint pk_Cookbooks primary key(RecipeId,MemberId) 
); 
+0

Dzięki za szybką odpowiedź, wygląda dobrze, dostaję tylko 1 problem. Otrzymuję ten błąd: "Relacja referencyjna spowoduje cykliczne odwołanie, które jest niedozwolone. [Nazwa ograniczenia = FK_Cookbooks_Members_MemberId]" Zakładam, że jest on powiązany z moim AuthorId w elemencie Recipe, ale nie jestem pewien. – Pricey

+1

Dzięki to świetnie, znalazłem podobne posty, ale nie zrozumiałem idei używania WithMany() bez wyrażenia lambda do skonfigurowania relacji, która będzie wymagana: wiele bez właściwości nawigacji po drugiej stronie relacji. Ma to więcej sensu, gdy patrzę na to, jak ten sam autor jest powiązany z wieloma przepisami. Dzięki! Chciałbym jeszcze raz dać +1. – Pricey

+0

Powoduje to również, że powinienem nieco zmienić strukturę i użyć opcjonalnej flagi właściciela w tabeli mapowania powiązań między "Książkami" i zlikwidować własność autora, ale nie jestem pewien, czy możesz dodać właściwości do produktu mapy (). – Pricey

Powiązane problemy