I have a simple WCF service hosted in IIS7 using the HTTP protocol. The service contains a method which returns a custom object called Calendar
. This object is very basic, and contains simple value-type properties, with the exception of one property, Holidays
, which is of type List<IHoliday>
. Holiday
is again, a simple type comprised of value-type properties only.
The Calendar
object is returned from the WCF service-method to an MVC controller, and is applied to a corresponding view. During memory-testing using dotTrace, it's apparent that the Calendar object is finalised by the GC, but interestingly, its Holidays
property, which is empty, remains on the heap.
It's not a major performance-issue, taking up a mere 32 bytes, but I'm interested to know why the empty list is not disposed. I can provide code-samples, if necessary.
Source code and service configuration below:
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();
}
}
Service Method:
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);
}
}
Service Configuration:
<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>