In rare (and bizzare) cases, I can't simply detach an entity from the context while it's still open! Why might that be true?

Robert Gustafson 606 Reputation points
2022-05-18T02:36:19.797+00:00

WHAT I HAVE:
Visual Basic 2019+, WinForms, .NET Framework 4.6+, Entity Framework (I'm not sure which version; I think 6), SQL Server (version unsure)

MY ISSUE:
For reasons too long and complex to explain here, I'm occasionally forced by my VB.NET app and entity data model to load in a reference to an entity instance (to different variables) twice while in the data context. Since EF doesn't allow multiple references to 1 entity to be attached simultaneously, I have to detach the 1st variable, using .Entry/.State to change it from EntityState.Unchanged to EntityState.Detached, prior to performing the 2nd query. Normally this works just fine. However, for 1 specific entity type in my app, and under very specific scenarios (that are ostensibly the same as others), the statement to detach instead sets the 1st reference to EntityState.Added, triggering either one of 2 exceptions, usually at the .SaveChanges statement: either I'm trying to multi-attach the entity to the context, or I'm trying to add it to the database when it's already present.

BTW, I never get an exception from the very statement that sets the state to EntityState.Detached. Also, I've defined my model using ***Model****-First* approach--good when you don't have to inherit an existing database from a non-EF app, and you want to keep the process of setting up the model simple.

A surefire way to guarantee detachment is to close the context and re-open it prior to the 2nd query, but that, I suspect, has 2 problems: 1) If the database is big, then performance penalties, and 2) not being able to "transactionalize" changes made after the 1st query and then the 2nd, so that they both succeed or fail together.

Long story short, I need to know if it's a bug in my version of EF (I think it's EF6, but don't hold me to that!), or if there's something wrong with the way the class for that particular entity is set up? (Full disclosure: The classes for the types where detachment works and the 1 where it doesn't always are not fundamentally different, and they all use Partial Class logic to augment them with additional, non-mapped, members.)

Something like this is what I do:

Using db = *context*
   Dim x = *query to get entity instance*
   db.Entry(x).State = EntityState.Detached 'usually, but not invariably, works
   '   some other code
   ...
   Dim y = *query to get collection including previous instance*
   '   some other code
   ...
   db.SaveChanges() 'occasionally triggers an exception for 1 entity-type because detaching failed
End Using

Please keep any recommendations in VB.NET and as simple as possible.

PS. Setting the 1st variable to a clone of the entity instance (which is therefore un-attached), rather than detaching, seems to solve the problem flawlessly, but I still need to know why simple detachment through .Entry/.State sometimes fails, given that cloning using EF logic has limitations--say, if navigation properties have to remain populated (a solution to that might be the somewhat laborious manual creation of a deep copy).

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,836 questions
.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,401 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,580 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Karen Payne MVP 35,196 Reputation points
    2022-05-19T23:45:19.18+00:00

    Sometimes EF can get confused, try the following.

    db.Entry(x).Reload()
    db.Entry(x).State = EntityState.Detached