question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

EF requires all model properties to be virtual in order to remove relationship without loading first

See original GitHub issue

Take this setup:

public class Foo
{
    public int Id { get; set; }
    public string Something { get; set; }
    public virtual Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }
}

public class ApplicationDbContext : DbContext
{
    public virtual IDbSet<Foo> Foos { get; set; }
    public virtual IDbSet<Bar> Bars { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Bar)
            .WithMany();
    }
}

If I do the following:

using (var context = new ApplicationDbContext())
{
    var foo = new Foo { Bar = new Bar() };
    context.Foos.Add(foo);
    context.SaveChanges();
}

using (var context = new ApplicationDbContext())
{
    var foo = context.Foos.OrderByDescending(f => f.Id).First();
    foo.Bar = null;
    context.SaveChanges();
}

then I retrieve the Foo instance I was working with, the relationship to Bar reappears. The only apparent way to remove the relationship without calling Include() or forcing a lazy load of Foo.Bar is to make all of the properties on Foo virtual, like so:

public class Foo
{
    public virtual int Id { get; set; }
    public virtual string Something { get; set; }
    public virtual Bar Bar { get; set; }
}

If I fail to mark any one of its properties as virtual, I’m back to loading the navigation property first before I can delete it as in older versions of EF. There’s a handful of reasons that I don’t want to have to mark every single property on my class as virtual. Is this a bug or is this by design? If the latter, why?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ajcvickerscommented, Jan 31, 2018

@joelmdev EF6 has two forms of proxies:

  • Lazy loading proxies, which only require navigation properties to be virtual and which only override the getter to do lazy loading.
  • Change tracking proxies, which allow changes to the entity to be detected without the need for EF to scan for changes and therefore override the setter.

It is true that setting to null could have been handled in the lazy-loading proxies such that they would have the behavior you are looking for. However, this was not something that was considered at the time the two kinds of proxies were implemented, and while we have considered adding it in later releases it would be a breaking change over the current behavior. If you’re interested, we would likely consider a PR for this, but it would likely have to be off by default with an option to switch it on.

/cc @divega

0reactions
ajcvickerscommented, Feb 12, 2018

@CZEMacLeod EF Core already supports INotifyPropertyChanging and INotifyPropertyChanged and I have filed https://github.com/aspnet/EntityFrameworkCore/issues/10949 for implementation of proxies that use this infrastructure. I don’t think we’re going to go back and add this to EF6 since it uses a different notification mechanism under the hood.

@divega I think we need figure out how to support this in EF Core without making the semantics of the proxies too obscure. It feels like it should probably one of the options for proxy generation that is beyond lazy loading only, but not full change tracking, and we have to figure out the best way to configure that–maybe UseProxies(SomeFlagEnum)?

With regard to setting IsLoaded, I don’t think it will help. IsLoaded just says that the relationship is loaded so EF won’t try to load it again, but it is perfectly valid for the navigation to be both loaded and null, so we can’t make an assumption that it has been changed to null.

Read more comments on GitHub >

github_iconTop Results From Across the Web

navigation property should be virtual - not required in ef ...
Since Lazy loading is not yet supported by EF Core, currently virtual have no special meaning. It would when (and if) they add...
Read more >
Introduction to relationships - EF Core
A relationship defines how two entities relate to each other. For example, when modeling posts in a blog, each post is related to...
Read more >
Changing Foreign Keys and Navigations - EF Core
How to change relationships between entities by manipulating foreign keys and navigations.
Read more >
Lazy Loading Related Data In Entity Framework Core
Lazy loading of data is a pattern whereby the retrieval of data from the database is deferred until it is needed.
Read more >
Configuring one-to-many Relationship in Entity ...
Most one-to-many relationships in an Entity Framework Core model follow conventions and require no additional configuration.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found