Entity Framework Core 1.1 В базе данных памяти не удается добавить новые объекты

entity-framework-core

Вопрос

Я использую следующий код в модульном тесте для тестовой установки:

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

Когда SaveChangesAsync достигнут, EF генерирует исключение ArgumentException со следующим сообщением:

Элемент с тем же ключом уже добавлен. Ключ: 1

Я также использую приспособление для модульного тестового класса, который заполняет базу данных объектами одинаковых типов, хотя для этого теста я хочу эту конкретную настройку, поэтому я хочу добавить эти новые объекты в базу данных в памяти. Я пробовал добавлять сущности на DbSet (а не DbContext) и добавлять все три объекта отдельно безрезультатно. Однако я могу добавить «simpleEntity» отдельно (потому что он не добавлен в прибор), но EF жалуется, как только я пытаюсь добавить «complexEntity» или «anotherEntity».

Кажется, что EF в базе данных памяти не может обрабатывать несколько надстроек над разными экземплярами контекста. Есть ли какое-либо обходное решение для этого или я делаю что-то неправильно в моей настройке?

База данных в этом случае является экземпляром этого класса:

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

Популярные ответы

Вы можете решить эту проблему, используя Collection Fixures, чтобы вы могли поделиться этим инструментом на нескольких тестовых классах. Таким образом, вы не создаете свой контекст несколько раз и, таким образом, вы не получите это исключение:

Некоторая информация о коллекции Fixture

Мой собственный пример:

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

}

Удачи, Seb



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow