2011-07-26 12 views
8

Otrzymuję klucz podstawowy błąd naruszenia gdy próbuję dodać element z wielu do wielu relacji:Dodanie artykułu z wielu-do-wielu relacji w Entity Framework

mam dwie klasy - Artykuły i tagi, które mają wiele do wielu relacji:

public class Article 
{ 
    public int ID { get; set; } 
    public string Text { get; set; } 
    public ICollection<Tag> Tags { get; set; } 
} 

public class Tag 
{ 
    [Key] 
    public string UrlSlug { get; set; } 
    public string Name { get; set; } 
    public ICollection<Article> Articles{ get; set; } 
} 

Kiedy dodać nowy artykuł i pozwala użytkownikowi na wejście żadnych tagów, a następnie chcę, aby utworzyć nowy tag jeśli Tag nie jest jeszcze utworzony bazy danych lub dodaj znacznik do kolekcji znaczników obiektu artykułu, jeśli znacznik już istnieje.

Dlatego gdy tworzę nowy artykuł obiekt nazwałbym poniższej funkcji:

public static Tag GetOrLoadTag(String tagStr) 
     { 
      string tagUrl = Tag.CreateTagUrl(tagStr); 
      var db = new SnippetContext(); 
      var tagFromDb = from tagdummy in db.Tags.Include(x => x.Articles) 
          where tagdummy.UrlSlug == tagUrl 
          select tagdummy; 
      if (tagFromDb.FirstOrDefault() != null) 
      { return tagFromDb.FirstOrDefault(); } 
      else 
      { 
       //create and send back a new Tag 
      } 

     } 

Funkcja ta zasadniczo sprawdza, czy jest dostępna Tag w bazie danych, a jeżeli tak powraca tego znacznika, który jest następnie dodawany do kolekcja Tag obiektu artykułu za pomocą article.Tags.Add().

Jednak gdy próbuję zapisać to za pomocą poniższego kodu otrzymuję naruszenie więzów błędu klucz podstawowy

db.Entry(article).State = EntityState.Modified; 
db.SaveChanges(); 

nie mogę dowiedzieć się, w jaki sposób powinny przejść o tylko tworzenie relacji między art i już istniejący Tag.

+0

Czy możesz podać więcej szczegółów i pełny kod? –

Odpowiedz

14

Użyj tej samej instancji kontekst dla całego przetwarzania operacji i swoim życiu będzie znacznie łatwiejsze:

using (var ctx = new MyContext()) 
{ 
    Article article = ctx.Articles.Single(a => a.Id == articleId); 
    Tag tag = ctx.Tags.SingleOrDefault(t => t.UrlSlug == tagUrl); 
    if (tag == null) 
    { 
     tag = new Tag() { ... } 
     ctx.Tags.AddObject(tag); 
    } 

    article.Tags.Add(tag); 
    ctx.SaveChanges(); 
} 

Jeśli nie chcesz ładować artykułu z bazy danych (zapytanie jest zbędne, jeśli wiesz, że istnieje) możesz użyć:

using (var ctx = new MyContext()) 
{ 
    Article article = new Article() { Id = articleId }; 
    ctx.Articles.Attach(article); 

    Tag tag = ctx.Tags.SingleOrDefalut(t => t.UrlSlug == tagUrl); 
    if (tag == null) 
    { 
     tag = new Tag() { ... } 
     ctx.Tags.AddObject(tag); 
    } 

    article.Tags.Add(tag); 
    ctx.SaveChanges(); 
} 
+0

Dzięki, że udało się. Wydaje mi się, że wiele osób jest włamywanych do Entity Framework przy użyciu innego Kontekstu. Problem polega na tym, że robienie wszystkiego w tej samej operacji jest sprzeczne z tym, jak zwykle programujemy DAL z różnymi operacjami. Najlepszym rozwiązaniem wydaje się przekazywanie kontekstu jako parametru ref. – Judo

+0

@Judo, dlatego Cię zapytałem "Więc upewnij się, że podczas pobierania tagu z db w kodzie używasz tego samego datacontekstu, którego używasz do wywoływania SaveChanges" –

+0

Trzeba tylko pamiętać, odkąd się tu natknąłem - jeśli "re ** abstrakcja kontekstu za wzorem repozytorium ** upewnij się, że możesz poprawnie ** udostępnić kontekst poprzez wtrysk/fabryka **. Ale jeśli podzielisz kontekst między metodami/zakresami, możesz napotkać problemy, w których ** nieudane zatwierdzenia przerywają kolejne niepowiązane zatwierdzenia ** - coś takiego jak ta "cofnij" może pomóc? http://rundevrun.blogspot.com/2012/06/entity-framework-removing-failed.html – drzaus

0

Jak tworzysz nowe tagi? I w jaki sposób dołączyć istniejący lub utworzony podmiot do artykułu.

Zastosowanie coś

Article a = new Article(...); 
a.tags.add(GetOrLoadTag("some tag")); 

Przeczytaj ten artykuł http://thedatafarm.com/blog/data-access/inserting-many-to-many-relationships-in-ef-with-or-without-a-join-entity/

+0

Jeśli istnieje znacznik, po prostu dodaję go za pomocą article.Tag.Add (existingTag). Ale kiedy próbuję go zapisać, generuje błąd naruszenia klucza głównego. – Judo

+0

Kiedy jest to tag exsisting, musisz poinformować framework, że jest to istniejąca jednostka. Struktura próbuje ponownie wstawić obiekt. Upewnij się, że ustawiłeś kolumnę tożsamości na kluczu podstawowym. –

+0

Dobrze, więc w jaki sposób pozwolić ramie poznać istniejącą jednostkę? – Judo

Powiązane problemy