Benjamin Diele
Benjamin Diele

Reputation: 1187

Why aren't my relations loaded?

I have the following entities:

public abstract class Meter
{
    public int MeterId { get; set; }
    public string EANNumber { get; set; }
    public string MeterNumber { get; set; }
    public abstract void AddReading(CounterReading reading);
}

public abstract class ElectricityMeter : Meter { }

public class SingleElectricityMeter : ElectricityMeter
{
    private Counter _counter = new Counter();
    public virtual Counter Counter
    {
        get { return _counter; }
        set { _counter = value; }
    }

    public override void AddReading(CounterReading reading)
    {
        Counter.Readings.Add(reading);
    }
}

public class Counter
{
    public int CounterId { get; set; }

    private ObservableCollection<CounterReading> _readings = new ObservableCollection<CounterReading>();

    public virtual ObservableCollection<CounterReading> Readings
    {
        get { return _readings; }
        set { _readings = value; }
    }


    [NotMapped]
    public CounterReading CurrentReading
    {
        get
        {
            return Readings.MaxBy(m => m.Reading);
        }
    }
}

When I set the Counter relation in runtime, everything works perfect. When I try to load the saved data, my Counter object isn't loaded (it's the default Counter, and not the one with the data from my database).

Is this still because I'm using inheritance in my Meter? My database looks decent enough with foreign keys: enter image description here

Edit Retrieving other nested entities works without problem. enter image description here

Upvotes: 1

Views: 72

Answers (1)

Gert Arnold
Gert Arnold

Reputation: 109253

SingleElectricityMeter.Counter is a (reference) navigation property. In your code it is always initialized by

private Counter _counter = new Counter();

But you shouldn't initialize reference properties. EF will think they're loaded and won't load them from the database. So just remove the initialization. But be careful...

The encapsulation of adding readings in the top-level class is a good idea from an OO point of view, but in the context of Entity Framework (or any ORM) it comes with a caveat. In order to make this work you always have to ensure that a Meter is read from the database including the Counter and its Readings:

db.Meters.Include(m => m.Counter.Readings)

As long as you do this, EF will be tracking all objects it needs in order to notice that Readings causes a change it should store in the database.

Also, by doing so it is safe to access Counter.CurrentReading. Otherwise this might trigger lazy loading (may not be bad, but can be inefficient) or cause an error if this happens after the context has been disposed.

Upvotes: 3

Related Questions