-1

我有一个使用 HTTP 协议托管在 IIS7 中的简单 WCF 服务。该服务包含一个方法,该方法返回一个名为 的自定义对象Calendar。这个对象是非常基本的,并且包含简单的值类型属性,除了一个属性,Holidays,它的类型是List<IHoliday>Holiday又是一个仅由值类型属性组成的简单类型。

Calendar对象从 WCF 服务方法返回到 MVC 控制器,并应用于相应的视图。在使用 dotTrace 进行内存测试期间,很明显 Calendar 对象已由 GC 完成,但有趣的Holidays是,它的空属性仍保留在堆上。

这不是主要的性能问题,仅占用 32 个字节,但我很想知道为什么没有处理空列表。如有必要,我可以提供代码示例。

源代码和服务配置如下:

public class Calendar : ICalendar
{
    [DataMember] private IEnumerable<IHoliday> holidays = new List<IHoliday>();
    [DataMember] private IEnumerable<IHolidayNotTaken> holidaysNotTaken = new List<IHolidayNotTaken>();
    [DataMember] private IEnumerable<INonInstructionalDay> nonInstructionalDays = new List<INonInstructionalDay>();
    [DataMember] private IEnumerable<ISchoolBreak> schoolBreaks = new List<ISchoolBreak>();
}

public class Holiday : IHoliday, IIdentifiable, IDisposable
{
    [DataMember(Name = @"date")] [JsonProperty(PropertyName = @"date")] private string date;

    [DataMember(Name = @"checked")]
    [JsonProperty(PropertyName = @"checked")]
    public bool Checked { get; set; }

    /// <summary>
    ///   Gets or sets the end Holiday Id.
    /// </summary>
    /// <value> The holiday id. </value>
    [DataMember(Name = @"id")]
    [JsonProperty(PropertyName = @"id")]
    public int HolidayId { get; set; }

    /// <summary>
    ///   Gets or sets the end description for the holiday.
    /// </summary>
    /// <value> The description. </value>
    [DataMember(Name = @"description")]
    [JsonProperty(PropertyName = @"description")]
    public string Description { get; set; }

    /// <summary>
    ///   Gets or sets the date of the holiday.
    /// </summary>
    /// <value> The holiday date. </value>
    [DataMember]
    [JsonIgnore]
    public DateTime Date { get; set; }

    /// <summary>
    ///   Gets or sets the sort order for the holiday.
    /// </summary>
    /// <value> The sort order. </value>
    [DataMember(Name = @"sortOrder")]
    [JsonProperty(PropertyName = @"sortOrder")]
    public int SortOrder { get; set; }

    /// <summary>
    ///   Gets the <see cref="IIdentifiable.Type" /> of this instance.
    /// </summary>
    [DataMember(Name = @"type")]
    [JsonProperty(PropertyName = @"type")]
    public string Type { get; private set; }

    /// <summary>
    ///   Invoked when this instance is serialising.
    /// </summary>
    /// <param name="streamingContext"> The streaming context. </param>
    [OnSerializing]
    private void OnSerialising(StreamingContext streamingContext)
    {
        date = Date.ToString(@"yyyy-MM-dd");
        Type = GetType().ToString();
    }
}

服务方式:

public Domain.Calendar GetCalendarByMember(string externalId)
    {
        try
        {
            using (var e = new EPlannerEntities())
            {
                var memberId = e.Members
                    .Where(m => m.ExternalId == externalId)
                    .Select(m => m.MemberId)
                    .SingleOrDefault();

                if (memberId.Equals(0))
                {
                    e.Members.AddObject(new Member { ExternalId = externalId.Trim() });

                    var calendar = new Domain.Calendar
                                   {
                                       DefaultViewId = 2,
                                       MemberId = memberId,
                                       IsWeekendsVisible = true,
                                       TimeFormatId = 1,
                                       DayBeginTime = new TimeSpan(0, 8, 0, 0),
                                       DayEndTime = new TimeSpan(0, 16, 0, 0),
                                       DateFormatId = 1
                                   };

                    e.Calendars.AddObject(calendar);
                    e.SaveChanges();

                    return calendar;
                }

                return e.Calendars.Single(c => c.MemberId == memberId);
            }
        }
        catch (Exception exception)
        {
            throw ErrorManager.FaultException(ExceptionType.Business, (int) CalendarErrorCodes.GeneralError, exception);
        }
    }

服务配置:

<services>
  <service behaviorConfiguration="CalendarServiceBehavior" name="HMH.ePlanner.Services.Calendar">
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="TCPBinding" name="TCPEndPoint" contract="HMH.ePlanner.Services.ICalendar">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="HTTPBinding" name="HttpEndPoint" contract="HMH.ePlanner.Services.ICalendar" />
    <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" name="TCPMexEndPoint" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:808/Calendar.svc" />
      </baseAddresses>
    </host>
  </service>
</services>
4

3 回答 3

1

问题源于Holiday列表在没有指定UpperBound. 指定 UpperBound 可确保在垃圾收集后从堆中删除对象。

于 2012-06-14T12:01:13.067 回答
0

对于您的问题,我没有答案,因为我在提供的代码中看不到任何犯罪行为。

我能提出的唯一建议是检查Session解决方案中是否需要安全性。

现在不一致了。配置为使用 TCP 的客户端启用它并为 HTTP 禁用它。

配置中缺少PS bindingConfiguration。你把所有的都发了吗?

于 2012-06-13T15:00:08.407 回答
0

为 Calendar 创建一个部分类(如果需要部分类)并向其中添加IDisposable接口并手动取消假期。再次运行 dottrace,看看是否会发生同样的情况。

于 2012-06-13T14:44:18.183 回答