Entity Framework Core 1.1 In der Arbeitsspeicher-Datenbank schlägt das Hinzufügen neuer Entitäten fehl

entity-framework-core

Frage

Ich verwende den folgenden Code in einem Komponententest für die Testkonfiguration:

var simpleEntity = new SimpleEntity();
var complexEntity = new ComplexEntity
{
    JoinEntity1List = new List<JoinEntity1>
    {
        new JoinEntity1
        {
            JoinEntity2List = new List<JoinEntity2>
            {
                new JoinEntity2
                {
                    SimpleEntity = simpleEntity
                }
            }
        }
    }
};
var anotherEntity = new AnotherEntity
{
    ComplexEntity = complexEntity1
};

using (var context = databaseFixture.GetContext())
{
    context.Add(anotherEntity);
    await context.SaveChangesAsync();
}

Wenn SaveChangesAsync erreicht ist, löst EF eine ArgumentException mit der folgenden Nachricht aus:

Ein Artikel mit demselben Schlüssel wurde bereits hinzugefügt. Schlüssel: 1

Ich benutze auch ein Fixture für die Unit-Test-Klasse, die die Datenbank mit Objekten des gleichen Typs füllt, obwohl ich für diesen Test dieses spezielle Setup möchte, also möchte ich diese neuen Entitäten der In-Memory-Datenbank hinzufügen. Ich habe versucht, die Entitäten auf dem DbSet (nicht den DbContext) hinzuzufügen und alle drei Entitäten separat zu addieren, ohne Erfolg. Ich kann jedoch "simpleEntity" separat hinzufügen (weil es nicht im Fixture hinzugefügt wird), aber EF beschwert sich, sobald ich versuche, "complexEntity" oder "anotherEntity" hinzuzufügen.

Es scheint, dass EF in der Speicherdatenbank nicht mehrere Adds über verschiedene Instanzen des Kontexts verarbeiten kann. Gibt es einen Workaround dafür oder mache ich etwas falsch in meinem Setup?

Die DatenbankFixture ist in diesem Fall eine Instanz dieser Klasse:

namespace Test.Shared.Fixture
{
    using Data.Access;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.DependencyInjection;

    public class InMemoryDatabaseFixture : IDatabaseFixture
    {
        private readonly DbContextOptions<MyContext> contextOptions;

        public InMemoryDatabaseFixture()
        {
            var serviceProvider = new ServiceCollection()
            .AddEntityFrameworkInMemoryDatabase()
            .BuildServiceProvider();

            var builder = new DbContextOptionsBuilder<MyContext>();
            builder.UseInMemoryDatabase()
                   .UseInternalServiceProvider(serviceProvider);

            contextOptions = builder.Options;
        }

        public MyContext GetContext()
        {
            return new MyContext(contextOptions);
        }
    }
}

Beliebte Antwort

Sie können mithilfe Sammlung Fixtures dieses Problem lösen , so dass Sie diese Befestigung über mehrere Testklassen teilen können. Auf diese Weise erstellen Sie Ihren Kontext nicht mehrere Male und Sie erhalten daher diese Ausnahme nicht:

Einige Informationen zur Sammlung Fixture

Mein eigenes Beispiel:

[CollectionDefinition("Database collection")]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{  }

[Collection("Database collection")]
public class GetCitiesCmdHandlerTests : IClassFixture<MapperFixture>
{
    private readonly TecCoreDbContext _context;
    private readonly IMapper _mapper;

    public GetCitiesCmdHandlerTests(DatabaseFixture dbFixture, MapperFixture mapFixture)
    {
        _context = dbFixture.Context;
        _mapper = mapFixture.Mapper;
    }

    [Theory]
    [MemberData(nameof(HandleTestData))]
    public async void Handle_ShouldReturnCountries_AccordingToRequest(
        GetCitiesCommand command,
        int expectedCount)
    {
        (...)
    }

    public static readonly IEnumerable<object[]> HandleTestData
        = new List<object[]>
        {
            (...)
        };
}

}

Viel Glück, Seb



Related

Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow