Entity Framework только установит свойство связанной сущности «null», если я сначала получу свойство

c# entity-framework entity-framework-6

Вопрос

Редактировать Это похоже на любое свойство Entity, которое ссылается на другой объект в одном направлении. Другими словами, для приведенного ниже примера тот факт, что Bar отменяет равенство, кажется, не имеет значения.

Предположим, что у меня есть следующие классы:

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

Обратите внимание, что здесь «Бар» намеренно имеет равенство «ИД», поскольку он более или менее представляет собой таблицу поиска - поэтому любые две ссылки на объекты с одним и тем же идентификатором всегда должны считаться одинаковыми.

Вот странная часть, все это прекрасно работает, когда я устанавливаю Foo.Bar в другой экземпляр Bar - все обновляется, как ожидалось.

Однако, если foo имеет существующий Bar когда он извлекается из DbContext и я делаю:

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

то свойство на самом деле не меняется!

Если я сделаю:

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

Тогда свойство будет фактически устанавливать и сохранять как null.

Поскольку свойство Foo.Bar является просто виртуальным, автоматически реализованным свойством, я могу только сделать вывод, что это имеет отношение к ленивым загрузкам и прокси-сайтам Entity Framework, но почему этот конкретный сценарий вызывает проблему, я понятия не имею.

Почему Entity Framework ведет себя так, и как я могу заставить его реально установить null ?

Популярные ответы

В качестве обходного пути самым простым способом, который я нашел для смягчения этой проблемы, является то, что сеттер вызывает геттер, прежде чем устанавливать для поля поддержки значение null, например

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

Таким образом, свойство работает независимо от того, действительно ли другой код действительно загрузил свойство, за счет потенциально ненужной нагрузки объекта.




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему