4 Stimmen

Entity Framework - Code First speichert viele zu viele Beziehungen

Ich habe zwei Klassen:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Email { get; set; }

    public virtual ICollection<Company> Companies { get; set; }
}

In meiner MVC-Anwendung Controller erhalten neue Firma von Post. Ich möchte den aktuellen Benutzer zum erstellten Unternehmen in etwa so hinzufügen.

User user = GetCurrentLoggedUser();
//company.Users = new ICollection<User>(); // Users is null :/
company.Users.Add(user);  // NullReferenceException
companyRepository.InsertOrUpdate(company);
companyRepository.Save();

Wie sollte es aussehen, damit es richtig funktioniert? Ich weiß es noch nicht, aber nach dem Hinzufügen von Benutzern zur Sammlung erwarte ich Probleme beim Speichern in der Datenbank. Für jeden Tipp, wie es aussehen sollte, wäre ich dankbar.

6voto

Ladislav Mrnka Punkte 355028

Verwenden Sie diesen Ansatz:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set;}

    private ICollection<User> _users;
    public ICollection<User> Users
    {
        get
        {
            return _users ?? (_users = new HashSet<User>());
        }
        set
        {
            _users = value;
        }
    }
}

HashSet ist besser als andere Sammlungen, wenn Sie auch die Equals y GetHashCode in Ihren Einrichtungen. Es wird Duplikate für Sie behandeln. Auch die träge Initialisierung von Sammlungen ist besser. Ich erinnere mich nicht mehr genau, aber ich glaube, ich hatte einige Probleme in einer meiner ersten EF-Testanwendungen, als ich die Sammlung im Konstruktor initialisierte und außerdem dynamische Proxies für träges Laden und Änderungsverfolgung verwendete.

Es gibt zwei Arten von Entitäten: losgelöste und angehängte. Eine angehängte Entität wird bereits durch den Kontext verfolgt. Normalerweise erhält man die angehängte Entität durch eine Linq-to-Entities-Abfrage oder durch den Aufruf von Create en DbSet . Eine abgetrennte Einheit wird nicht durch den Kontext verfolgt, aber sobald Sie die Attach o Add bei der Einstellung, diese Entität anzuhängen, werden alle damit verbundenen Entitäten ebenfalls angehängt / hinzugefügt. Das einzige Problem, mit dem Sie bei der Arbeit mit abgetrennten Entitäten konfrontiert werden, ist, wenn die verwandte Entität bereits in der Datenbank vorhanden ist und Sie nur eine neue Beziehung erstellen möchten.

Die wichtigste Regel, die Sie verstehen müssen, ist der Unterschied zwischen den Methoden Add und Attach:

  • Add wird alle abgetrennten Entitäten im Graphen als Added => Alle zugehörigen Entitäten werden als neue Entitäten eingefügt.
  • Attach wird alle abgetrennten Entitäten im Graphen als Unchanged => Sie müssen manuell angeben, was geändert wurde.

Sie können den Status jeder angehängten Entität manuell einstellen, indem Sie

context.Entry<TEntity>(entity).State = EntityState....;

Bei der Arbeit mit abgetrennten Many-to-Many-Elementen müssen Sie in der Regel diese Techniken verwenden, um nur Beziehungen aufzubauen, anstatt doppelte Elemente in die Datenbank einzufügen.

Meiner Erfahrung nach ist es sehr schwierig, mit abgetrennten Entitätsgraphen zu arbeiten, vor allem nach dem Löschen von Beziehungen. Deshalb lade ich immer Entitätsgraphen aus der Datenbank und führe Änderungen manuell in die angehängten Graphen ein, die in der Lage sind, alle Änderungen für mich vollständig nachzuvollziehen.

Beachten Sie, dass Sie Entitäten aus verschiedenen Kontexten nicht mischen können. Wenn Sie eine Entität aus einem Kontext in einen anderen einbinden wollen, müssen Sie die Entität zuerst explizit aus dem ersten Kontext lösen. Ich hoffe, Sie können das tun, indem Sie den Status auf Detached im ersten Kontext.

2voto

jessegavin Punkte 70339

In Ihrem Konstruktor für die Entität Unternehmen können Sie eine leere Auflistung für die Eigenschaft Benutzer erstellen.

public class Company
{
    public Company() {
      Users = new Collection<User>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

Was das Speichern in der Datenbank betrifft, so habe ich vor ein paar Tagen eine ähnliche Frage gestellt und mir wurde versichert, dass Entity Framework in der Lage ist, die Änderungen an verwandten Entitäten zu verfolgen. Lesen Sie hier mehr darüber:

Werden untergeordnete Einheiten automatisch verfolgt, wenn sie zu einer übergeordneten Einheit hinzugefügt werden?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X