简体   繁体   中英

List contains one object why?

I have a problem where an object containing a list property holds 1 item, which it shouldn't (it should be empty).

The Station class contains a list of edges (List Edges). The Edge class have a EndStation, which is of the type Station.

The problem is, after returning the IQueryable from GetEdgesByStartStation(), the EndStation on each Edge contains a list of edges (List Edges) which is not empty (as it should). The item in the list are the Station (edge.EndStation) it self. I've tried to illustrate it with comments in the code below

public IQueryable<Edge> GetEdgesByStartStation(Station station)
{
    var edges = db.Edges.Where(x => x.StartStationId.Equals(station.ID));
    foreach (var edge in edges)
    {
        edge.EndStation = db.Stations.FirstOrDefault(x => x.ID.Equals(edge.EndStationId)); 
        //Here the edge.EndStation.Edges would contain 1 item, edge.EndStation 
        //eg. edge.EndStation = "Miami", edge.EndStation.Edges = { "Miami" }
    }

    return edges;
}

What I wanted this code to do, was get all the edges for the Station passed to the method. For each edge, connect a EndStation with an empty list of edges.

Station class:

public partial class Station
{
    public Station()
    {
        this.Reservations = new List<Reservation>();
        this.StationMaintenances = new List<StationMaintenance>();
    }

    [DataMember]
    //[JsonConverter(typeof(Int32))] 
    public int ID { get; set; }
    [DataMember]
    //[JsonConverter(typeof(Int32))] 
    public int TypeId { get; set; }
    [DataMember]
    public string Title { get; set; }
    [DataMember]
    public string Description { get; set; }
    [DataMember]
    public decimal StationLat { get; set; }
    [DataMember]
    public decimal StationLong { get; set; }
    [DataMember]
    public bool IsOperational { get; set; }
    [DataMember]
    public bool IsActive { get; set; }
    [DataMember]
    public DateTime CreatedDate { get; set; }
    [DataMember]
    public virtual BatteryStorage BatteryStorages { get; set; }
    [DataMember]
    public virtual List<Reservation> Reservations { get; set; }
    [DataMember]
    public virtual List<StationMaintenance> StationMaintenances { get; set; }
    [DataMember]
    public virtual List<Edge> Edges { get; set; }
    [DataMember]
    public virtual StationType StationType { get; set; }
}

Edge class:

public partial class Edge
{
    [DataMember]
    public int ID { get; set; }
    [DataMember]
    public int StartStationId { get; set; }
    [DataMember]
    public int EndStationId { get; set; }
    [DataMember]
    public virtual Station EndStation { get; set; }
    [DataMember]
    public decimal Distance { get; set; }
    [DataMember]
    public decimal Time { get; set; }
    [DataMember]
    public bool IsActive { get; set; }

}

How can this be?

That's called relationship fixup .

Station EndStation and List<Edge> Edges are on the opposite sides of the same relationship.
When materializing object from the Db (the edge.EndStation = ... line) the EF figures out that the opposite side is your 'edge' which it already has in the memory - so it does the fixup and fills that in, whether you like it or not.

You should take a look at this answer here for some details LazyLoadingEnabled setting doesn't seem to work in EF 5

As @Slauma mentioned, I don't think there is a way of disabling that - I'm guessing it's just logical to have both filled (if no extra loading from Db is required).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM