使用 Include(...) 返回具有导航属性的实体时失去连接

Losing connection when returning entity with navigational properties using Include(...)

在深入挖掘和混淆错误消息之后,我找到了这个示例(我认为这是重现该问题的最小示例)。我几乎可以肯定地得出结论,问题的出现是由于与我要返回的实体相关联的实体。

[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;
}

如果我使用 Copy() 激活该行(它创建一个新的站点实例并复制除记录之外的所有属性,它通过本身)。但是,当我只是添加站点而不创建副本时(无论我是否保留记录、使它们无效或设置一个空列表),它都不会很好地滚动。

自从我使用了 Include(),被处置的对象就不再是问题了。我收到的错误消息在控制台中是这样说的。

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

谷歌搜索给了我很多关于 Apache 的参考资料(我在 IIS 上 运行),PHP(我在 .NET 上构建它)和证书的安全问题(我没有使用任何其他调用效果很好)。

所以我怀疑错误消息是误导性的,来自一台混乱的计算机,或者我在我的设置中遗漏了一些东西。自动生成的 类 反映了我添加到表中的外键,看起来像这样。

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

我没有看到任何关于如何排除故障的想法。这个错误不应该发生。另一方面——福岛也不应该发生。但确实如此。

我终于明白了 运行。

  1. 关闭代理创建。
  2. 关闭延迟加载。
  3. 使虚拟 属性 可忽略以进行序列化。
  4. 显式加载链接实体。

前两项在上下文的构造函数中完成。

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

第三个是通过将导致循环依赖的虚拟属性之一归因于对序列化无效。

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

最后一项是包含或省略要显示(或不显示)的导航属性。在这种情况下,将有关站点的信息塞入每条记录中是有意义的。不过,可以在没有记录的情况下显示站点。

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

话说回来,会有龙。这种方法会导致大量工作,因为每次 re-created 时都需要手动 re-edit auto-generated 文件。所以我选择了代码优先。