2015-05-08 4 views
5

Angenommen, ein Kunde hat viele Telefonnummern und eine Telefonnummer hat nur einen Kunden.Entity Framework richtige Möglichkeit, Sammlung in einem zu ersetzen viele

public class PhoneNumber : IValueObject { 
    public string Number {get; set;} 
    public string Type {get; set;} 
} 

public class Customer : IEntity { 
    public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support 
    public void SetPhones(params PhoneNumber[] phones) { 
     this.phones.Clear(); 
     this.phones.AddRange(phones); 
    } 
} 

Wenn ich ein EF-Mapping wie dies tun, und führen Sie es, jedes Mal wenn ich Telefonnummern setzen sie neue Phonenumbers erstellen, aber die alten nicht löschen. Es gibt keine anderen Entitäten, die auf Telefonnummern verweisen, ich stelle sie nicht einmal auf meinem dbcontext offen, gibt es eine Möglichkeit, EF mitzuteilen, dass Customer vollständig PhoneNumbers besitzt und daher, wenn Telefonnummern aus der Sammlung entfernt wurden, sollten sie gelöscht werden?

proof

Ich weiß, dass ein Dutzend Möglichkeiten gibt es, um dieses Problem zu hacken, aber dies ist nicht ein seltsamer Rand Fall, was der „richtige“ Weg, dies zu handhaben.

+0

Ich denke, umgekehrt ist möglich, wenn Sie Telefonnummern löschen würde Form dbset und Cascade auf löschen ist dann wird es in was genau Sie wollten :) –

+0

@JenishRabadiya Ich denke, dass mit Kaskade auf löschen könnte ich vielleicht Telefonnummern haben speziell über Änderung gelöscht, wenn 'Customer' zu löschen, aber das ist ... –

+0

Bitte senden Sie das Teil des Codes, wo Sie versuchen, eine' PhoneNumber' von einem 'Customer' zu entfernen. –

Antwort

6

I gleiche Frage, die genaue hatte :)

Diese Antwort auf identifying relationships gelöst mein Problem.

Hinweis: Sie müssen die Sammlung (eifrig, explizit oder träge) laden, damit sie vor dem Einstellen der neuen Werte und dem Aufruf von save verfolgt werden kann. Andernfalls werden Sie die Sammlung nicht ersetzen, sondern einfach hinzufügen.

Zum Beispiel:

var entity = unitOfWork.EntityRepository.GetById(model.Id); 
// I have something like this to load collection because 
// I don't have the collection's entities exposed to the context 
unitOfWork.EntityRepository.LoadCollection(entity, e => e.CollectionProperty); 
entity.CollectionProperty = newCollectionValuesList; 
unitOfWork.Save(); 

Dies wird die bisherige Sammlung Werte aus der Sammlung Tabelle 'entfernen und nur die neu eingestellten Werte hinzufügen.

Hoffe, dass hilft.

+0

+1 dafür, dass die Dinge richtig gemacht werden und Repositories aus einer Arbeitseinheit "herausfließen". Ich bekomme die Antwort aber immer noch nicht richtig. Wie würde "Entity" hier aussehen? Willst du damit sagen, dass dieser Trick mit der Telefonnummer ids * alone * genug ist, um einen Löschvorgang richtig auszulösen? –

+0

@GeorgeMauer - Entity hier wäre Ihre 'Customer' und' CollectionProperty' wäre Ihre 'phones' Eigenschaft. In meinem Fall lade ich meine Sammlungen explizit, so dass "LoadCollection" aussieht wie "context.Entry (entity) .Collection (navigationProperty) .Load();" unter der Haube. Wenn Sie eine identifizierende Beziehung zwischen dem Kunden und Phone haben, und Sie haben geladen 'phones' für einen Kunden dann sollte der Code in Ihrem Screenshot lassen Sie mit nur 123-456-7890 in der Tabelle Phonenumbers. –

1

First (optional):

Ich empfehle Ihnen

public ICollection<PhoneNumber> phones {get; private set;}

eine virtual Eigentum zu machen, lassen Sie das Entity Framework wissen, dass es geladen faul sein sollte (auch wenn Sie haben keine Lazy Load aktiviert, es ist eine gute Praxis).

public virtual ICollection<PhoneNumber> phones {get; private set;}

Zweite:

hinzufügen Inverse Navigation Property auf Ihrer PhoneNumber Klasse (es wird erforderlich sein, um die Lösung, die ich Ihnen unten geben zu erreichen):

public class PhoneNumber : IValueObject { 
    public string Number {get; set;} 
    public string Type {get; set;} 

    public virtual Customer {get; set;} 
} 

public class Customer : IEntity { 
    public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support 
    public void SetPhones(params PhoneNumber[] phones) { 
     this.phones.Clear(); 
     this.phones.AddRange(phones); 
    } 
} 

Dritte (Possib le Lösung für Ihr Problem):

Entfernen Sie die PhoneNumber Objekte aus Context stattdessen so aus dem Customer tun:

public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support 
    public void SetPhones(params PhoneNumber[] phones) { 
     Context.PhoneNumbers.RemoveRange(this.phones); 
     this.phones.AddRange(phones); 
    } 
} 
+0

Fehler bei der 'Update-Database' . 'Beim Speichern von Entitäten, die keine Fremdschlüsseleigenschaften für ihre Beziehungen aufweisen, ist ein Fehler aufgetreten. Die EntityEntries-Eigenschaft gibt null zurück, da eine einzelne Entität nicht als Quelle der Ausnahme identifiziert werden kann. Die Behandlung von Ausnahmen während des Speicherns kann vereinfacht werden, indem Sie die Eigenschaften von Fremdschlüsseln in Ihren Entitätstypen angeben ... Eine Beziehung aus dem AssociationSet 'Customer_phones' befindet sich im Status 'Gelöscht'. In Anbetracht Vielzahl Zwänge, eine entsprechende ‚Customer_phones_Target‘ muss auch in der ‚Gelöschte‘ –

+0

Staat erzielen @GeorgeMauer den dritten Schritt versuchen, zu kommentieren und tun nur die ersten beiden. Sie sollten ausreichen, um Ihr Problem zu lösen. –

+0

Ich habe den dritten Schritt bearbeitet. Kannst du das bitte versuchen? –