Losing connection when returning entity with navig

2019-09-19 13:26发布

After quite some digging and confusing error messages, I've arrived at this sample (which I believe to be the smallest example reproducing the issue). I can almost certainly conclude that the issue appears due to the entity linked to the one that I'm returning.

[OperationContract]
[WebGet(UriTemplate = "Stations")]
List<Station> GetStations();

public List<Station> GetStations()
{
  List<Station> stations = new List<Station>();
  using (Context context = new Context())
    foreach (Station station in context.Stations.Include(element => element.Records))
      //stations.Add(station.Copy());
      stations.Add(station);

  return stations;
}

It works if I activate the line with Copy() (which creates a new instance of a station and copies over all the properties except for the records, which it creates by itself). However, when I just add the stations without creating a copy (regardless of whether I keep the records, nullify them or set en empty list), it doesn't roll well.

Since I used Include(), the objects being disposed isn't the issue anymore. The error message I get says in the console like so.

http://localhost:25760/MyService.svc/Stations net::ERR_CONNECTION_RESET

Googling that gave me a lot of references to Apache (I'm running it on IIS), PHP (I'm building it on .NET) and security issues with certificates (I'm not using any and the other calls work well).

So my suspicion is either that the error message is misleading coming from a confused computer or that I'm missing something in my setup. The autogenerated classes reflect the foreign key I added to the tables and look like this.

alter table Records 
add constraint FkStationId 
foreign key (StationId) 
references Stations (Id)

public partial class Record
{
  public System.Guid Id { get; set; }
  public Nullable<System.Guid> StationId { get; set; }
  ...
  public virtual Station Station { get; set; }
}

public partial class Station
{
  [System.Diagnostics.CodeAnalysis.SuppressMessage(
    "Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
  public Station() { this.Records = new HashSet<Record>(); }
  public System.Guid Id { get; set; }
  ...
  [System.Diagnostics.CodeAnalysis.SuppressMessage(
    "Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
  public virtual ICollection<Record> Records { get; set; }
}

I see nothing that leads me to any idea on how to trouble-shoot it. This error shouldn't happen. On the other hand - Fukushima shouldn't happen neither. But it did.

1条回答
地球回转人心会变
2楼-- · 2019-09-19 14:11

Finally I got this running.

  1. Turn off proxy creation.
  2. Turn off lazy loading.
  3. Make virtual property ignorable to serialization.
  4. Load in the linked entity explicitly.

The first two items are done in the constructor of the context.

public partial class Context : DbContext
{
  public Context() : base("name=ContextConnection")
  {
    Configuration.LazyLoadingEnabled = false;
    Configuration.ProxyCreationEnabled = false;
  }
  ...
}

The third is done by attributing one of the virtual properties that lead to circular dependency as not valid for serialization.

public partial class Station
{
  ...
  [IgnoreDataMemeber]
  public virtual ICollection<Record> Records { get; set; }
}

The last one is including or omitting the navigational property to be (or not to be displayed). In this case, it made sense to jam in the information about stations into each record. The stations can be presented without the records, though.

public List<Station> GetStations()
{
  using (Context context = new Context())
    return context.Stations
      .ToList();
}

public List<Record> GetRecords()
{
  using (Context context = new Context())
    return context.Records
      .Include(record => record.Station)
      .ToList();
}

Having said that, there will be dragons. This approach leads to a lot of work as it requires to manually re-edit the auto-generated files each time they're re-created. So i went with Code First, instead.

查看更多
登录 后发表回答