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.

Disconnected entities not recognized as existing

See original GitHub issue

I am attempting a simple scenario of adding a disconnected entity, retrieved from one DbContext, to a different entity that is saved within another DbContext.

I have a basic DbContext implementation:

public class EfTestDbContext : DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Author> Authors { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseInMemoryDatabase();
    }
}

and two simple entities:

public class Author
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class Book
{
    public int ID { get; set; }

    public int AuthorID { get; set; }
    public Author Author { get; set; }
    
    public string Name { get; set; }
}

and I am creating and saving the Author entity within one context, then adding it to the Book entity within the other context:

static void Main(string[] args)
{
    Author existingAuthor;
    using (var ctx = new EfTestDbContext())
    {
        existingAuthor = new Author() { Name = "First author" };

        ctx.Add(existingAuthor);
        ctx.SaveChanges();
        Console.WriteLine($"Saved author ({existingAuthor.Name})");
    }

    using (var ctx = new EfTestDbContext())
    {
        var book1 = new Book()
        {
            Name = "First book",
            Author = existingAuthor
        };

        Console.WriteLine($"Added author ({existingAuthor.Name}) to first book");
        Console.WriteLine($"Author is existing: {ctx.Entry(existingAuthor).IsKeySet}");

        ctx.Add(book1);
        ctx.SaveChanges();
    }
}

Although the contexts are separate and the Author entity is disconnected once the first context is disposed, the existingAuthor entity is recognized as existing, since ctx.Entry(existingAuthor).IsKeySet returns True.

I have read the document at https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities and from what I understand, the IsKeySet value should be enough to let EF know that the entity already exists in the database and it should not attempt to insert it.

In this example I’m using the In-Memory provider, but I’ve attempted this with SQLite and the result has been the same.

Is this a bug, or am I doing something wrong? Have I understood the document wrong and should I be manually and explicitly tracking which entities have a IsKeySet value set and which do not?

EF Core version: 2.1.1.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
skyflyercommented, Aug 19, 2018

I also performed tests with the latest version of EF (release/2.2 branch) and the results are the same.

I’m out of my depth in examining the true reason, but I tracked it to NavigationFixer.cs:191 where this existing entity is attached as Added when traversing navigation property of the parent (Book) object. I noticed that change tracker is searching for existing entities in the context in order to determine whether an entity should be added or not (which contradicts with what is written in https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities or more probably, I’m misreading it):

https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities#with-auto-generated-keys

… On the other hand, if the key value has been set, then it must have already been previously saved and now needs updating. …

That lead me to manually attach the disconnected entity using ctx.Attach(existingAuthor) and then everything worked – this approach is possible in simple example such as the provided test, but quite hard to achieve with repository implementations in different contexts.

So the puzzle remains - is there something special we need to tell EF that it should detected the entities correctly as modified?

0reactions
skyflyercommented, Aug 21, 2018

@ajcvickers, I have observed what you write in practice, so it makes perfect sense. The reason Patrik opened this ticket is because we were actually investigating why this does not work according to the docs. I suppose we could agree that the docs are a little misleading. Take this paragraph for example (emphasis mine):

The value of an automatically generated key can often be used to determine whether an entity needs to be inserted or updated. If the key has not been set (that is, it still has the CLR default value of null, zero, etc.), then the entity must be new and needs inserting. On the other hand, if the key value has been set, then it must have already been previously saved and now needs updating. In other words, if the key has a value, then the entity was queried, sent to the client, and has now come back to be updated.

Anyhow, now that we know what is going on behind the scenes, we’re all set. I was afraid we were doing something wrong or stumbling on a bug, but it has obviously been designed that way.

I appreciate your time responding to this issue. Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Disconnected entities not recognized as existing #13051
I am attempting a simple scenario of adding a disconnected entity, retrieved from one DbContext, to a different entity that is saved within ......
Read more >
Disconnected Entities - EF Core
Working with disconnected, untracked entities across multiple context instances in Entity Framework Core.
Read more >
How to work with disconnected entities in Entity Framework ...
Learn how you can track changes to entities while disconnected from the EF context in Entity Framework Core.
Read more >
Working with disconnected entities - EF6
This topic discusses different options that are available when using Entity Framework with disconnected entities.
Read more >
How to Update Existing Disconnected Entity
It taking a disconnected entity, finding it in the database, and applying the changes. Is there a better way to do this? I...
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