I searched for the answer to the following problem for several days, still without any luck, any help is much appreciated.
Disclaimer : WCF and EntityFramework are concepts of a new type, but .NET, C #, web services, concepts of relational object mapping, of course, are not.
I inherited an application with a client application, using the WCF service to retrieve and save a Matter object that contains a one-to-many relationship with CaseNotesLog objects.
The client can successfully complete certain questions with 0, 1 or many child CaseNotesLog objects, he can also successfully save questions with added, updated or deleted CaseNotesLog objects.
So far, so good, however, there seems to be a set of questions, with CaseNotesLog child objects that can be read successfully but cannot be saved, even if they were not changed at all.
In essence, this is similar to the process of deserializing to WCF while saving a Matter object that loses the CaseNotesLog child entries.
To clarify:
- Reading
- There is 1 child CaseNotesLog record in the database in the material record,
- this successfully translates into an EntityFramework Matter object with a child CaseNotesLog on the server.
- it successfully serializes / deserializes through the WCF service and correctly populates the Matter object using a child CaseNotesLog on the client side.
- Save
- the Matter client object with a child CaseNotesLog object "leaves" the client application.
- it is serialized for transmission through the WCF service back to the server.
- viewing the trace log of this serialization contains the CaseNotesLog child register.
- this object is deserialized on the server side.
- By adding trace instructions to the Setter code in the body objectโs MATML object, I can observe how CaseNotesLog children fit correctly in the parent matter.
- BUT, once the getter function is called, the collection is empty
As if the RelationshipManager collection reset somewhere else.
The end result is that the Matter object with the CaseNotesLog child object leaves my code on the client side, but although it looks like it is being serialized / deserialized correctly by the time I get to check the state of the object on the server Next to the child entries.
To check, I added some code to the entityframework class to keep an independent count of how large the children's collection is. It is set to 1 during the Set operation when the CaseNotesLog collection is installed, and it remains at 1 when the CaseNotesLog collection is retrieved during Get, even if the collection was empty.
To add to the confusion * this does not apply to all issues, some seem to work, others not * this does not seem to apply to all types of child objects that seem to work on other sets.
The WCF service, among other methods, implements the following:
[ServiceContract] public interface IMattersService { ... [OperationContract] Matter ReadMatter(int matterID); ... [OperationContract] void SaveMatter(Matter matter); ... } }
It is implemented as follows:
public class MattersService : IMattersService { ... public Matter ReadMatter(int matterID) { using (var repo = new MatterRepository()) { try { return repo.ReadMatter(matterID); } catch (Exception ex) { Logger.Write(ex, "Error", 0); throw; } } } ... public void SaveMatter(Matter matter) { Trace.WriteLine(matter.CaseNotesLogs.Count); using (var repo = new MatterRepository()) { try { repo.SaveMatter(matter); } catch (Exception ex) { Logger.Write(ex, "Error", 0); throw; } } } ... }
Matter is the generated EntityFramework class:
/// <summary> /// No Metadata Documentation available. /// </summary> [EdmEntityTypeAttribute(NamespaceName="EDDSolutionsLtd.Services.Data", Name="Matter")] [Serializable()] [DataContractAttribute(IsReference=true)] public partial class Matter : EntityObject { ... /// <summary> /// No Metadata Documentation available. /// </summary> [XmlIgnoreAttribute()] [SoapIgnoreAttribute()] [DataMemberAttribute()] [EdmRelationshipNavigationPropertyAttribute("EDDSolutionsLtd.Services.Data", "MatterCaseNotesLog", "CaseNotesLog")] public EntityCollection<CaseNotesLog> CaseNotesLogs { get { return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<CaseNotesLog>("EDDSolutionsLtd.Services.Data.MatterCaseNotesLog", "CaseNotesLog"); } set { if ((value != null)) { ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<CaseNotesLog>("EDDSolutionsLtd.Services.Data.MatterCaseNotesLog", "CaseNotesLog", value); } } } ... }
In the modified version, I added some entries:
public int CheckCaseNotesLogsCount { get; set; } public EntityCollection<CaseNotesLog> CheckCaseNotesLogs { get; set; } /// <summary> /// No Metadata Documentation available. /// </summary> [XmlIgnoreAttribute()] [SoapIgnoreAttribute()] [DataMemberAttribute()] [EdmRelationshipNavigationPropertyAttribute("EDDSolutionsLtd.Services.Data", "MatterCaseNotesLog", "CaseNotesLog")] public EntityCollection<CaseNotesLog> CaseNotesLogs { get { if (CheckCaseNotesLogs != null) { Trace.WriteLine("GET ACTUAL CheckCaseNotesLogs[" + CheckCaseNotesLogs.Count + "]"); } Trace.WriteLine("GET ACTUAL CheckCaseNotesLogsCount[" + CheckCaseNotesLogsCount + "]"); StackTrace st = new StackTrace(); int i = ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<CaseNotesLog>("EDDSolutionsLtd.Services.Data.MatterCaseNotesLog", "CaseNotesLog").Count; Trace.WriteLine("GET ACTUAL value[" + i + "]"); Trace.WriteLine(st.ToString()); return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<CaseNotesLog>("EDDSolutionsLtd.Services.Data.MatterCaseNotesLog", "CaseNotesLog"); } set { if ((value != null)) { CheckCaseNotesLogs = value; CheckCaseNotesLogsCount = value.Count; Trace.WriteLine("SET ACTUAL value[" + value.Count + "]"); ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<CaseNotesLog>("EDDSolutionsLtd.Services.Data.MatterCaseNotesLog", "CaseNotesLog", value); Trace.WriteLine("SET ACTUAL Property value[" + this.CaseNotesLogs.Count + "]"); } else { Trace.WriteLine("SET NULL Value"); } } }
This is a snippet of a Soap message received by the Wcf service showing a Child CaseNotesLog entry.
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"> <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"> <EventID>0</EventID> <Type>3</Type> <SubType Name="Information">0</SubType> <Level>8</Level> <TimeCreated SystemTime="2011-05-19T22:49:34.7968750Z" /> <Source Name="System.ServiceModel.MessageLogging" /> <Correlation ActivityID="{fa25d214-04e9-4b16-8ae8-3de7b9a12bc6}" /> <Execution ProcessName="WebDev.WebServer40" ProcessID="2332" ThreadID="13" /> <Channel /> <Computer>EDD-MERCURY</Computer> </System> <ApplicationData> <TraceData> <DataItem> <MessageLogTraceRecord Time="2011-05-19T23:49:34.7812500+01:00" Source="ServiceLevelReceiveRequest" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace"> <HttpRequest> <Method>POST</Method> <QueryString></QueryString> <WebHeaders> <Content-Length>142631</Content-Length> <Content-Type>application/soap+xml; charset=utf-8</Content-Type> <Expect>100-continue</Expect> <Host>localhost:58080</Host> <VsDebuggerCausalityData> uIDPo7kHl/h9zQNAkghvTvB5/u8AAAAAuoDOged1MUm+UmudC0H6u3k/74R6jUpIn/o2sS4KNxYACQAA</VsDebuggerCausalityData> </WebHeaders> </HttpRequest> <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"> <s:Header> <a:Action s:mustUnderstand="1"> http://tempuri.org/IMattersService/SaveMatter</a:Action> <a:MessageID> urn:uuid:f1d751a7-1012-4268-b7da-87a12cf6d14f</a:MessageID> <ActivityId CorrelationId="4f53460f-8880-4b6e-aa66-557fa90d4ae3" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics"> fa25d214-04e9-4b16-8ae8-3de7b9a12bc6</ActivityId> <a:ReplyTo> <a:Address> http://www.w3.org/2005/08/addressing/anonymous</a:Address> </a:ReplyTo> <a:To s:mustUnderstand="1"> http://localhost:58080/MattersService.svc</a:To> </s:Header> <s:Body> <SaveMatter xmlns="http://tempuri.org/"> <matter z:Id="i1" xmlns:b="http://schemas.datacontract.org/2004/07/EDDSolutionsLtd.Services.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <EntityKey z:Id="i2" xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:c="http://schemas.datacontract.org/2004/07/System.Data"> <c:EntityContainerName> EDDSolutionsLtdEntities</c:EntityContainerName> <c:EntityKeyValues> <c:EntityKeyMember> <c:Key>ID</c:Key> <c:Value i:type="d:int" xmlns:d="http://www.w3.org/2001/XMLSchema"> 180</c:Value> </c:EntityKeyMember> </c:EntityKeyValues> <c:EntitySetName>Matters</c:EntitySetName> </EntityKey> <b:AllRecordsReceivedDate i:nil="true"> </b:AllRecordsReceivedDate> <b:BeginClaimDate i:nil="true"> </b:BeginClaimDate> ... <b:CaseEmailLogs></b:CaseEmailLogs> <b:CaseFileLogs></b:CaseFileLogs> <b:CaseNotesLogs> <b:CaseNotesLog z:Id="i3"> <EntityKey z:Id="i4" xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:c="http://schemas.datacontract.org/2004/07/System.Data"> <c:EntityContainerName> EDDSolutionsLtdEntities</c:EntityContainerName> <c:EntityKeyValues> <c:EntityKeyMember> <c:Key>ID</c:Key> <c:Value i:type="d:int" xmlns:d="http://www.w3.org/2001/XMLSchema"> 281</c:Value> </c:EntityKeyMember> </c:EntityKeyValues> <c:EntitySetName> CaseNotesLogs</c:EntitySetName> </EntityKey> <b:ActivityDate> 2011-05-18T00:00:00</b:ActivityDate> <b:Body i:nil="true"></b:Body> <b:Comment>3</b:Comment> <b:ContactID>608</b:ContactID> <b:CreatedBy>mminns</b:CreatedBy> <b:CreatedOn> 2011-05-19T15:25:03.923</b:CreatedOn> <b:ID>281</b:ID> <b:MatterId>180</b:MatterId> <b:ModifiedBy>mminns</b:ModifiedBy> <b:ModifiedOn> 2011-05-19T15:25:03.923</b:ModifiedOn> <b:OriginalContactID>0</b:OriginalContactID> <b:Outcome>Unknown</b:Outcome> <b:Subject>1</b:Subject> </b:CaseNotesLog> </b:CaseNotesLogs> ... </matter> </SaveMatter> </s:Body> </s:Envelope> </MessageLogTraceRecord> </DataItem> </TraceData> </ApplicationData> </E2ETraceEvent>