Entity Framework Core 1.1 In Memory échoue lors de l'ajout de nouvelles entités

entity-framework-core

Question

J'utilise le code suivant dans un test unitaire pour la configuration du test:

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();
}

Lorsque SaveChangesAsync est atteint, EF lève une exception ArgumentException avec le message suivant:

Un article avec la même clé a déjà été ajouté. Clé: 1

J'utilise également un appareil pour la classe de test unitaire qui remplit la base de données avec des objets du même type, bien que, pour ce test, je souhaite cette configuration particulière et que je veuille ajouter ces nouvelles entités à la base de données in memory. J'ai essayé d'ajouter les entités sur le DbSet (pas le DbContext) et d'ajouter les trois entités séparément, mais en vain. Je peux cependant ajouter "simpleEntity" séparément (car il n'est pas ajouté dans l'appareil) mais EF se plaint dès que j'essaie d'ajouter "complexEntity" ou "anotherEntity".

Il semble que EF dans la base de données en mémoire ne puisse pas gérer plusieurs ajouts sur différentes instances du contexte. Existe-t-il une solution de contournement ou est-ce que je fais quelque chose de mal dans ma configuration?

DatabaseFixture dans ce cas est une instance de cette classe:

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);
        }
    }
}

Réponse populaire

Vous pouvez résoudre ce problème en utilisant Collection Fixtures afin de pouvoir partager ce montage entre plusieurs classes de test. De cette façon, vous ne créez pas votre contexte plusieurs fois et vous n'obtiendrez donc pas cette exception:

Quelques informations sur la collection Fixture

Mon propre exemple:

[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[]>
        {
            (...)
        };
}

}

Bonne chance, Seb



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi