Ich habe eine Beziehung von vielen zu vielen, kurz
Cases -----< CaseSubjectRelationships >------ CaseSubjects
Ausführlicher: Fälle( ID , CaseTypeID, .......)
CaseSubjects( ID , DisplayName, CRMSPIN)
CaseSubjectsRelationships( FallID , BetreffID , PrimarySubject, RelationToCase, ...)
In meiner Many-to-many-Verknüpfungstabelle befinden sich zusätzliche Eigenschaften, die sich auf die Verbindung des Betreffs mit dem spezifischen Fall beziehen - z. B. Startdatum, Enddatum, Freitextbeziehung zum Fall (Beobachter, Ersteller usw.)
Es wurde ein Entity Framework-Datenmodell erstellt - ASP.NET Version 4.0
Ich habe einen WCF-Dienst mit einer Methode namens CreateNewCase
die als Parameter eine Case
Objekt (eine vom Entity Framework erstellte Entität) - seine Aufgabe ist es, den Fall in der Datenbank zu speichern.
Der WCF-Dienst wird von einem Tool eines Drittanbieters aufgerufen. Hier wird das SOAP gesendet:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<CreateNewCase xmlns="http://tempuri.org/">
<c xmlns:a="http://schemas.datacontract.org/2004/07/CAMSModel">
<a:CaseSubjectsRelationships>
<a:CaseSubjectsRelationship>
<a:CaseSubject>
<a:CRMSPIN>601</a:CRMSPIN>
<a:DisplayName>Fred Flintstone</a:DisplayName>
</a:CaseSubject>
<a:PrimarySubject>true</a:PrimarySubject>
<a:RelationToCase>Interested</a:RelationToCase>
<a:StartDate>2011-07-12T00:00:00</a:StartDate>
</a:CaseSubjectsRelationship>
<a:CaseSubjectsRelationship>
<a:CaseSubject>
<a:CRMSPIN>602</a:CRMSPIN>
<a:DisplayName>Barney Rubble</a:DisplayName>
</a:CaseSubject>
<a:RelationToCase>Observer</a:RelationToCase>
<a:StartDate>2011-07-12T00:00:00</a:StartDate>
</a:CaseSubjectsRelationship>
</a:CaseSubjectsRelationships>
<a:CaseType>
<a:Identifier>Change of Occupier</a:Identifier>
</a:CaseType>
<a:Description>Case description</a:Description>
<a:Priority>5</a:Priority>
<a:QueueIdentifier>Queue One</a:QueueIdentifier>
<a:Title>Case title</a:Title>
</c>
</CreateNewCase>
</s:Body>
</s:Envelope>
Die WCF-Engine deserialisiert dies in eine Case-Entität für mich richtig, und wenn ich im Debugger sehe, ist alles richtig eingerichtet.
Was ich tun möchte, ist nur eine neue CaseSubject
wenn es nicht bereits einen Eintrag mit diesem Namen in der Datenbank gibt CRMSPIN
angegeben (CRMSPIN ist eine Referenznummer aus einer zentralen Kundendatenbank)
Im folgenden Beispiel möchte ich also sehen, ob ich bereits einen Eintrag in CaseSubjects
für jemanden mit CRMSPIN 601, und wenn ich das tue, möchte ich keinen weiteren (doppelten) Eintrag erstellen, sondern den neuen Fall mit dem bestehenden Thema verknüpfen (obwohl natürlich eine neue Zeile in CaseSubjectsRelationships mit den spezifischen "zusätzlichen" Informationen wie Beziehung usw. erstellt werden muss)
Hier ist der .NET-Code, den ich versucht habe, dies zu tun.
Public Class CamsService
Implements ICamsService
Public Function CreateNewCase(c As CAMSModel.Case) As String Implements ICamsService.CreateNewCase
Using ctx As New CAMSEntities
' Find the case type '
Dim ct = ctx.CaseTypes.SingleOrDefault(Function(x) x.Identifier.ToUpper = c.CaseType.Identifier.ToUpper)
' Give an error if no such case type '
If ct Is Nothing Then
Throw New CaseTypeInvalidException(String.Format("The case type {0} is not valid.", c.CaseType.Identifier.ToString))
End If
' Set the case type based on that found in database: '
c.CaseType = ct
For Each csr In c.CaseSubjectsRelationships
Dim spin As String = csr.CaseSubject.CRMSPIN
Dim s As CaseSubject = ctx.CaseSubjects.SingleOrDefault(Function(x) x.CRMSPIN = spin)
If Not s Is Nothing Then
' The subject has been found based on CRMSPIN so set the subject in the relationship '
csr.CaseSubject = s
End If
Next
c.CreationChannel = "Web service"
c.CreationDate = Now.Date
' Save it '
ctx.AddToCases(c)
ctx.SaveChanges()
End Using
' Return the case reference '
Return c.ID.ToString
End Function
End Class
Wie Sie sehen können, wird stattdessen die For Each
Schleife versuche ich, einen Betreff auf der Grundlage der CRMSPIN zu erhalten, und wenn ich etwas erhalte, aktualisiere ich die Entität "CaseSubject". (Ich habe auch versucht csr.SubjectID = s.ID
anstatt die gesamte Einheit zu setzen, und ich habe auch versucht, sie beide zu setzen!)
Doch selbst wenn man einen Haltepunkt an der ctx.SaveChanges()
Zeile, und wenn man sich anschaut, wie die Fächer eingerichtet sind und im Debugger sieht, dass es gut aussieht, ist es siempre Erstellung einer neuen Zeile in der Tabelle CaseSubjects.
Ich kann sehen, im Prinzip sollte dies funktionieren - Sie werden sehen, ich habe genau das Gleiche für Case Type getan - ich habe den Bezeichner in der XML gesendet ausgewählt, fand die Entität mit diesem Bezeichner über den Kontext, dann änderte der Fall die .CaseType
zu der von mir gefundenen Einrichtung. Wenn es speichert, funktioniert es perfekt und wie erwartet und ohne duplizierte Zeilen.
Ich habe nur Schwierigkeiten, die gleiche Theorie auf eine Seite einer Many-to-many-Beziehung anzuwenden.
Hier sind einige (hoffentlich relevante) Auszüge aus der .edmx
<EntitySet Name="Cases" EntityType="CAMSModel.Store.Cases" store:Type="Tables" Schema="dbo" />
<EntitySet Name="CaseSubjects" EntityType="CAMSModel.Store.CaseSubjects" store:Type="Tables" Schema="dbo" />
<EntitySet Name="CaseSubjectsRelationships" EntityType="CAMSModel.Store.CaseSubjectsRelationships" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_CaseSubjectsRelationships_Cases" Association="CAMSModel.Store.FK_CaseSubjectsRelationships_Cases">
<End Role="Cases" EntitySet="Cases" />
<End Role="CaseSubjectsRelationships" EntitySet="CaseSubjectsRelationships" />
</AssociationSet>
<AssociationSet Name="FK_CaseSubjectsRelationships_CaseSubjects" Association="CAMSModel.Store.FK_CaseSubjectsRelationships_CaseSubjects">
<End Role="CaseSubjects" EntitySet="CaseSubjects" />
<End Role="CaseSubjectsRelationships" EntitySet="CaseSubjectsRelationships" />
</AssociationSet>
EDIT: Die Eigenschaftssetzer für die CaseSubject
Eigenschaft der CaseSubjectsRelationships
Objekt:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
<XmlIgnoreAttribute()>
<SoapIgnoreAttribute()>
<DataMemberAttribute()>
<EdmRelationshipNavigationPropertyAttribute("CAMSModel", "FK_CaseSubjectsRelationships_CaseSubjects", "CaseSubject")>
Public Property CaseSubject() As CaseSubject
Get
Return CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of CaseSubject)("CAMSModel.FK_CaseSubjectsRelationships_CaseSubjects", "CaseSubject").Value
End Get
Set
CType(Me, IEntityWithRelationships).RelationshipManager.GetRelatedReference(Of CaseSubject)("CAMSModel.FK_CaseSubjectsRelationships_CaseSubjects", "CaseSubject").Value = value
End Set
End Property