【问题标题】:WCF deserialization losing child collectionsWCF 反序列化丢失子集合
【发布时间】:2011-05-20 09:56:34
【问题描述】:

我几天来一直在寻找以下问题的答案,到目前为止没有任何运气,非常感谢任何帮助。

免责声明:WCF 和 EntityFramework 对我来说是新概念,但 .NET、c#、Web 服务、对象关系映射概念肯定不是。

我继承了一个带有客户端应用程序的应用程序,该应用程序使用 WCF 服务来检索和保存一个“Matter”对象,该对象包含与“CaseNotesLog”对象的一对多关系。

客户端可以成功检索具有 0、1 或多个子 CaseNotesLog 对象的某些 Matters,它还可以成功保存添加、更新或删除 CaseNotesLog 对象的 Matters。

到目前为止一切都很好,但是似乎有一组 Matters,其中包含可以成功读取但即使根本没有更改也无法保存的子 CaseNotesLog 对象。

本质上,当保存 Matter 对象时,WCF 上的反序列化过程会丢失子 CaseNotesLog 条目。

澄清一下:

  1. 读取
    1. 一个 Matter 记录在数据库中有 1 个 CaseNotesLog 子记录,
    2. 这已成功转换为 EntityFramework Matter 对象,在服务器上有一个子 CaseNotesLog 对象
    3. 这已在 WCF 服务中成功序列化/反序列化,并在客户端正确填充了一个带有子 CaseNotesLog 的 Matter 对象。
  2. 保存
    1. 带有子 CaseNotesLog 对象的客户端 Matter 对象“离开”客户端应用程序。
    2. 这被序列化以通过 WCF 服务传递回服务器。
    3. 查看此序列化包含子 CaseNotesLog 的 Trace 日志记录。
    4. 此对象在服务器端反序列化
    5. 通过将跟踪语句添加到实体框架 Matter 对象中的 Setter 代码中,我可以观察到 CaseNotesLog 子项被正确放置到父组中。
    6. 但只要调用 Getter 功能,集合就是空的

就好像关系管理器集合正在其他地方被重置。

最终结果是带有子 CaseNotesLog 对象的 Matter 对象将我的代码留在了客户端,但是当我检查服务器上对象的状态时,它看起来正在正确序列化/反序列化- 侧面的孩子记录已经消失了。

为了检查,我在实体框架类中添加了一些代码,以独立计算子集合的大小。在设置 CaseNotesLog 集合时在 Set 操作期间将其设置为 1,在 Get 期间检索到 CaseNotesLog 集合时保持为 1,即使该集合已被清空。

增加混乱 *这不适用于所有事项,有些似乎有效,有些则无效 *这似乎不适用于所有类型的子对象,其他集合似乎可以工作。

WCF 服务以及其他方法实现了以下功能:

[ServiceContract]
public interface IMattersService
{
    ...
    [OperationContract]
    Matter ReadMatter(int matterID);
    ...
    [OperationContract]
    void SaveMatter(Matter matter);
    ...
    }
}

实现如下:

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 是一个 EntityFramework 生成的类:

/// <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);
            }
        }
    }
    ...
}

我添加了一些日志记录的损坏版本:

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");
        }
    }
}

这是 Wcf 服务接收到的 Soap 消息的 sn-p,显示子 CaseNotesLog 记录存在。

<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>                  

【问题讨论】:

  • 抱歉,这不是答案,但我无法对 OP 发表评论以提出问题。我假设您将其保存到 SQL Server 数据库;您是否能够将 SQL 事件探查器附加到它以查看在保存/获取时通过网络服务器从网络服务器发送到数据库的确切内容?您的数据库可能出于某种原因删除子记录(在插入/更新或存储过程中触发)。这应该可以帮助您确定问题是由您的数据库还是 EF 引起的。

标签: c# .net wcf


【解决方案1】:

您能否为数据协定标记此属性:System.Runtime.Serialization.DataContractAttribute(IsReference=true)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多