2012-07-25 2 views
10

Ich habe folgende Entity Framework Code ersten Code. Die Tabellen werden erstellt und Daten werden eingefügt. Es gibt jedoch doppelte Datensätze in der Club-Tabelle.Entity Framework: Doppelte Datensätze in Viele-zu-Viele-Beziehung

Meine Operationen sind: -

  1. erstellen Clubs

    Schaffung App Club
  2. Personen erstellen Person App

Wie Sie den doppelten Eintrag zu vermeiden?

enter image description here

static void Main(string[] args) 
    { 
     Database.SetInitializer<NerdDinners>(new MyInitializer()); 

     CreateClubs(); 
     InsertPersons(); 

    } 

    public static void CreateClubs() 
    { 

     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      Club club1 = new Club(); 
      club1.ClubName = "club1"; 

      Club club2 = new Club(); 
      club2.ClubName = "club2"; 

      Club club3 = new Club(); 
      club3.ClubName = "club3"; 

      db.Clubs.Add(club1); 
      db.Clubs.Add(club2); 
      db.Clubs.Add(club3); 

      int recordsAffected = db.SaveChanges(); 


     } 
    } 

    public static Club GetClubs(string clubName) 
    { 
     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      //var query = db.Clubs.Where(p => p.ClubName == clubName); 
      var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName); 
      return query; 
     } 
    } 

    public static void InsertPersons() 
    { 
     string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
     using (var db = new NerdDinners(connectionstring)) 
     { 

      Club club1 = GetClubs("club1"); 
      Club club2 = GetClubs("club2"); 
      Club club3 = GetClubs("club3"); 

      Person p1 = new Person(); 
      p1.PersonName = "Person1"; 

      Person p2 = new Person(); 
      p2.PersonName = "Person2"; 

      List<Club> clubsForPerson1 = new List<Club>(); 
      clubsForPerson1.Add(club1); 
      clubsForPerson1.Add(club3); 

      List<Club> clubsForPerson2 = new List<Club>(); 
      clubsForPerson2.Add(club2); 
      clubsForPerson2.Add(club3); 

      p1.Clubs = clubsForPerson1; 
      p2.Clubs = clubsForPerson2; 

      db.Persons.Add(p1); 
      db.Persons.Add(p2); 

      int recordsAffected = db.SaveChanges(); 


     } 
    } 

Domain

public class Person 
{ 
    public int PersonId { get; set; } 
    public string PersonName { get; set; } 
    public virtual ICollection<Club> Clubs { get; set; } 
} 

public class Club 
{ 
    public int ClubId { get; set; } 
    public string ClubName { get; set; } 
    public virtual ICollection<Person> Members { get; set; } 
} 

//System.Data.Entity.DbContext is from EntityFramework.dll 
public class NerdDinners : System.Data.Entity.DbContext 
{ 

    public NerdDinners(string connString): base(connString) 
    { 

    } 

    protected override void OnModelCreating(DbModelBuilder modelbuilder) 
    { 
     //Fluent API - Plural Removal 
     modelbuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 

    public DbSet<Person> Persons { get; set; } 
    public DbSet<Club> Clubs { get; set; } 

} 
+1

Haben Sie es zweimal ausführen? – podiluska

+0

@podiluska. Nein, ich habe es nur einmal ausgeführt. – Lijo

Antwort

18

Das Problem ist, dass Sie mehrere Kontexte erstellen.

Zuerst erstellen Sie die Schläger. Es ist in Ordnung. Aber wenn Sie die Personen erstellen, holen Sie die Schläger über GetClubs, aber für jeden Club verfügen Sie über den tatsächlichen Entitätsrahmenkontext, so dass Sie mit getrennten Einheiten enden. Unter InsertPersons fügen Sie den neuen Personen getrennte Clubeinheiten hinzu, so dass der aktuelle Kontext der Meinung ist, dass es sich bei den Clubs um neue Clubs handelt.

Wenn Sie also einen Club zu einer Person hinzufügen, erstellen Sie neue Clubs.

Dies liegt daran, dass das Entity Framework die Änderungen verfolgt und die Entitäten pro Kontext verwaltet. Wenn Sie eine Entität zu einem Kontext hinzufügen, der sie noch nicht enthält, wird sie wie eine neue Entität behandelt.

Eigentlich sollte man so etwas wie dieses (nicht getestet) tun:

static void Main(string[] args) 
{ 
    Database.SetInitializer<NerdDinners>(new MyInitializer()); 

    string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; 
    using (var db = new NerdDinners(connectionstring)) 
    { 
     CreateClubs(db); 
     InsertPersons(db); 
    } 

} 

public static void CreateClubs(NerdDinners db) 
{ 
    Club club1 = new Club(); 
    club1.ClubName = "club1"; 

    Club club2 = new Club(); 
    club2.ClubName = "club2"; 

    Club club3 = new Club(); 
    club3.ClubName = "club3"; 

    db.Clubs.Add(club1); 
    db.Clubs.Add(club2); 
    db.Clubs.Add(club3); 

    int recordsAffected = db.SaveChanges(); 
} 

public static Club GetClubs(string clubName, NerdDinners db) 
{ 
    //var query = db.Clubs.Where(p => p.ClubName == clubName); 
    var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName); 
    return query; 
} 

public static void InsertPersons(NerdDinners db) 
{ 
    Club club1 = GetClubs("club1", db); 
    Club club2 = GetClubs("club2", db); 
    Club club3 = GetClubs("club3", db); 

    Person p1 = new Person(); 
    p1.PersonName = "Person1"; 

    Person p2 = new Person(); 
    p2.PersonName = "Person2"; 

    List<Club> clubsForPerson1 = new List<Club>(); 
    clubsForPerson1.Add(club1); 
    clubsForPerson1.Add(club3); 

    List<Club> clubsForPerson2 = new List<Club>(); 
    clubsForPerson2.Add(club2); 
    clubsForPerson2.Add(club3); 

    p1.Clubs = clubsForPerson1; 
    p2.Clubs = clubsForPerson2; 

    db.Persons.Add(p1); 
    db.Persons.Add(p2); 

    int recordsAffected = db.SaveChanges(); 
} 

Natürlich sollten Sie die Struktur dieser Code Refactoring, aber bitte beachten Sie, dass ich für meine Operationen nur ein EF-Kontext verwenden.

+0

siehe meine Bearbeitungen und Codebeispiel –

+0

In diesem Codebeispiel gibt es nur einen EF-Kontext. Ich brauche separate EF-Kontexte. Irgendwelche Gedanken? – Lijo

+1

Wenn Sie die Entitäten aus einer anderen Quelle als den tatsächlichen Kontext verwenden möchten, dann müssen Sie sie anhängen: http://msdn.microsoft.com/en-us/library/bb896271.aspx –

0

Dank @PeterPorfy

Lesen Sie auch Exception of type 'System.ObjectDisposedException'

I

verwendet
((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)entity); 

für die Objekte aus früheren Kontext zu befestigen.

Ein Beispiel für IEntityWithKey ich verwendet wird, ist wie folgt. Bitte kommentieren Sie, wenn Sie Probleme mit diesem Ansatz feststellen.

public class Person : IEntityWithKey 
{ 
    public int PersonId { get; set; } 
    public string PersonName { get; set; } 

    public EntityKey EntityKey { get; set; } 
} 

Bitte beachten Sie die folgende auch

  1. Problem with SaveChanges() Entity Framework 4.1
  2. Entity Framework Updating Many-To-Many Relationships - POCO

+0

Für diejenigen, die downvote - ich bin interessiert um zu sehen, warum es einen Downvote gibt. Stimmt etwas nicht mit dieser Antwort? – Lijo

+0

Ich denke, sie bevorzugen, dass Peters Antwort als die richtige markiert wird. Sag es einfach. – Miro

+0

Ich habe nicht downvoted. – Miro