Entity Framework will only set related entity property to "null" if I first get the property

c# entity-framework entity-framework-6

Question

Edit This seems to occur for any Entity property that references another entity in one direction. In other words, for the below example, the fact that Bar overrides Equality appears to be irrelevant.

Suppose I have the following classes:

public class Foo
{
    public int? Id { get; set; }

    public virtual Bar { get; set; }

}

public class Bar : IEquatable<Bar>
{
    public int Id { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as Bar;

        return Equals(other);
    }

    public bool Equals(Bar other)
    {
        if (object.Equals(other, null))
            return false;

        return this.Id == other.Id;
    }

    public static bool operator ==(Bar left, Bar right)
    {
        return object.Equals(left, right);
    }

    public static bool operator !=(Bar left, Bar right)
    {
        return !object.Equals(left, right);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Note that here, "Bar" intentionally has "Id" equality, because it more or less represents a lookup table - so any two object references with the same Id should always be considered the same.

Here's the weird part, this all works fine when I set Foo.Bar to another Bar instance - everything updates as expected.

However, if foo has an existing Bar when it is retrieved from the DbContext and I do:

foo.Bar = null

then the property doesn't actually change!

If I do:

var throwAway = foo.Bar;
foo.Bar = null;

Then the property will actually set and save as null.

Since the Foo.Bar property is simply a virtual, auto-implemented property, I can only conclude that this has something to do with lazy-loading and Entity Framework proxies - but why this particular scenario causes a problem, I have no idea.

Why does Entity Framework behave this way, and how can I get it to actually set null reliably?

1
4
2/11/2014 8:43:45 AM

Popular Answer

As a workaround, the easiest way I've found to mitigate this issue is to have the setter call the getter before setting the backing field to null, e.g.

public class Foo
{
    public int? Id { get; set; }

    private Bar _bar;
    public virtual Bar 
    { 
        get { return _bar; }

        set
        {
            var entityFrameworkHack = this.Bar; //ensure the proxy has loaded
            _bar = value;
        }
    }
}

This way, the property works regardless of whether other code has actually loaded the property yet, at the cost of a potentially unneeded entity load.

2
2/13/2014 7:35:17 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow