Search code examples
c#entity-framework-corexunit

EF Core (in-memory database) - 'The instance of entity type X cannot be tracked because another instance with the key value


I am using xunit with an Entity Framework in-memory database. For each test a new instance of my in memory database is created and then disposed.

I get the following error when running more than 1 tests.

System.InvalidOperationException: 'The instance of entity type 'Account_Master' cannot be tracked because another instance with the key value '{NUMBER_INT: 1}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.'

From what I can see the issue arises when I try and populate my in-memory database with fake test data. On the first test, I add an dummy account, and a dummy scope (these are referenced by foreign key). This works fine.

However on the next test, when I add the dummy scope, it automatically adds the dummy account (even though it should not know about it yet).

I have an example code project here https://github.com/welcometochristown/efCoreErrorTest

I have two database contexts in this project

FakeAccountContext
FakeSmtrSimpleContext

For some reason the FakeAccountContext works, but the FakeSmtrSimpleContext doesn't (even though they are nearly identical).

To reproduce error

Build project
Open the test explorer
Expand tests
Right click "SmtrSimpleTest" -> Run (error!)
Right click "AccountTest" -> Run (works!)

Using Microsoft.EntityFrameworkCore.InMemory (3.1.27)


Solution

  • I think the hypothesis about the static properties maintaining references to the entities between tests is correct.

    In the debugger, on the second test, in a breakpoint before the Account_Master.Add(), we can see that the static SmtrSimpleDummyAccount (an Account_Master) of the previous test still exists:

    Debugger display showing Account_Master exists before Add

    I changed the static properties to methods that return a new object, then forget it instead of maintaining a static reference to it:

     public static class FakeAccount
        {
            public static Account DummyAccount()
            {
                return new Account
                {
                    NUMBER_INT = 1,
                    SCOPE_CHR = FakeAccountScope.Public().SCOPE_CHR
                };
            }
    
    
            public static Account_Master SmtrSimpleDummyAccount()
            {
                return new Account_Master
                {
                    NUMBER_INT = 1,
                    SCOPE_CHR = "Public",
                };
            }
        }
    

    and

    public static class FakeAccountScope
        {
            public static AccountScope Private()
            {
                return new AccountScope
                {
                    SCOPE_CHR = nameof(Private)
                };
            }
    
            public static AccountScope Public()
            {
                return new AccountScope
                {
                    SCOPE_CHR = nameof(Public)
                };
            }
    
            public static X_Account_Scope SmtrSimplePublic()
            {
                return new X_Account_Scope
                {
                    SCOPE_CHR = nameof(Public)
                };
            }
    
            public static X_Account_Scope SmtrSimplePrivate()
            {
                return new X_Account_Scope
                {
                    SCOPE_CHR = nameof(Private)
                };
            }
    
        }
    

    And now all the tests pass:

    Tests pass

    Possibly also relevant for your FakeAccount.SmtrSimpleDummyAccount: How to create a static lambda for use with expression building?