C# 在内存数据库中共享索引?

标签 c# database unit-testing

所以我正在测试我的代码部分,在我的数据库中添加和删除数据。我正在为每个单元测试设置一个内存数据库,以确保我对每个测试都有一个完全“干净的平板”。但是,我遇到了一个非常奇怪的问题。我省略了下面的一些代码,但它显示了我的一般方法:

[TestFixture]
internal class EventControllerTest
{

    [Test]
    public void CreateEventController()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(databaseName: "CreateEventController1")
            .Options;
        var context = new ApplicationDbContext(options, null);

        //Add eventType.
        realEventService = new EventService(context, currentUserService.Object);
        realEventService.CreateEventType(new EventTypeData
        {
            Color = "Pink"
        });
        //ASSERTS
    }

    [Test]
    public void GetEventController()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(databaseName: "GetEventController1")
            .Options;
        var context = new ApplicationDbContext(options, null);

        //Add eventType.
        realEventService = new EventService(context, currentUserService.Object);
        realEventService.CreateEventType(new EventTypeData
        {
            Color = "Pink",
        });
      //ASSERTS
    }
}

现在,如果我自己运行这些测试中的每一个,它们就会通过,因为我最初检查 EventType 的 Id,它们都是 1。但是,如果我按顺序运行所有测试,我的第二个测试就会失败。它失败了,因为它添加的 EventType 实际上具有 2 而不是 1 的 id!但是,数据库只包含一个 EventType 条目。我在数据库上有不同的名称,据我所知,这意味着它们完全不同。然而,自动递增的索引由于某种原因刚刚增加并在我的第二次测试中使用。所以澄清一下:

  • 如果我运行 CreateEventController(),它的 EventType 条目将获得 id 一。
  • 如果我运行 GetEventController(),它的 EventType 条目将获得
    一。
  • 如果我运行 CreateEventController(),然后运行 ​​GetEventController(),
    CreateEventController() 中的 EventType 条目为 1,并且 EventType GetEventController() 中的条目 ID 为 2!

如何完全分离这些数据库?

最佳答案

看起来像是一个 Unresolved 问题/错误:https://github.com/aspnet/EntityFrameworkCore/issues/6872

他们确实提供了一个扩展方法作为修复(代码从那里提取):

public static class DbContextExtensions
{
    public static void ResetValueGenerators(this DbContext context)
    {
        var cache = context.GetService<IValueGeneratorCache>();
        foreach (var keyProperty in context.Model.GetEntityTypes()
            .Select(e => e.FindPrimaryKey().Properties[0])
            .Where(p => p.ClrType == typeof(int)
                        && p.ValueGenerated == ValueGenerated.OnAdd))
        {
            var generator = (ResettableValueGenerator)cache.GetOrAdd(
                keyProperty,
                keyProperty.DeclaringEntityType,
                (p, e) => new ResettableValueGenerator());

            generator.Reset();
        }
    }
}

public class ResettableValueGenerator : ValueGenerator<int>
{
    private int _current;

    public override bool GeneratesTemporaryValues => false;

    public override int Next(EntityEntry entry)
        => Interlocked.Increment(ref _current);

    public void Reset() => _current = 0;
}

To use, call context.ResetValueGenerators(); before the context is used for the first time and any time that EnsureDeleted is called. For example:

using (var context = new BlogContext())
{
    context.ResetValueGenerators();
    context.Database.EnsureDeleted();

    context.Posts.Add(new Post {Title = "Open source FTW", Blog = new Blog {Title = "One Unicorn"}});
    context.SaveChanges();
}

关于C# 在内存数据库中共享索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51562648/

相关文章:

c# - 只读取 HTML 文件的标题和/或 META 标签,不加载完整的 HTML 文件

c# - 如何将基于键的字典值绑定(bind)到代码隐藏中的 TextBlock?

C#:通用数学函数(Min、Max 等)

SecurityComponent 黑洞我的 Controller 测试用例

javascript - 如何对这段代码进行单元测试

c# - Silverlight:访问企业数据的最佳实践

database - 从 PostgreSQL 函数生成 HTML

php - cakephp 插入不同的表

database - 为 Google App Maker 记录添加多个所有者

c# - 替换部分模拟对象中的只读属性