You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core内存数据库中LINQ查询仅返回最后一个实体问题

EF Core 6.0.13按Mode过滤StopPoint仅返回单个实体的问题

我正在用Entity Framework Core 6.0.13开发一个返回数据库实体列表的方法,单元测试使用内存数据库填充测试数据,但按Mode过滤的查询只返回最后一个符合条件的实体,而非全部。

测试数据填充代码

private TopologyDBContext _topologyDbContext;
private StopPointRepository _stopPointRepository;

[SetUp]
public void Setup()
{
    // 创建内存测试数据库
    var options = new DbContextOptionsBuilder<TopologyDBContext>()
        .UseInMemoryDatabase(databaseName: "TopologyTestDB")
        .Options;

    _topologyDbContext = new TopologyDBContext(options);
    _stopPointRepository = new StopPointRepository(_topologyDbContext);

    SeedTestData();
}

[TearDown]
public void TearDown()
{
    _topologyDbContext.Database.EnsureDeleted();
}

private void SeedTestData()
{
    var typeCodeOne = new NaptanTypeCodes("RLY", "NaptanFerryBerth", false, "Ferry", "Stop", 85000);
    var typeCodeTwo = new NaptanTypeCodes("ntc2", "className2", false, "Air", "type2", 2);
    var typeCodeThree = new NaptanTypeCodes("ntc3", "className3", true, "BusCoach", "type3", 3);
    var typeCodeFour = new NaptanTypeCodes("ntc4", "className4", false, "BusCoach", "type4", 4);
    var typeCodeFive = new NaptanTypeCodes("ntc5", "className5", true, "BusCoach", "type5", 5);

    var modeFerry = new Mode("Ferry", "Description", null, null, true, null, null, null, null, null, true, null,
        DateTime.UtcNow, null, null, null, null, null, null, null);

    var modeAir = new Mode("Air", "Description", null, null, true, null, null, null, null, null, true, null,
        DateTime.UtcNow, null, null, null, null, null, null, null);

    var modeBusCoach = new Mode("BusCoach", "DescriptionOne", null, null, true, null, null, null, null, null, true, null,
        DateTime.UtcNow, null, null, null, null, null, null, null);

    var modeFerryList = new List<Mode>() {modeFerry};
    var modeAirList = new List<Mode>() { modeAir};
    var modeFerryAirList = new List<Mode>() { modeFerry, modeAir};
    var modeBusCoachList = new List<Mode>() { modeBusCoach};

    var stopPoint1 = new StopPoint("9100SIDCUP0", "Sidcup", "indicator1", "stopLetter1", 000, "910GSIDCUP",
        "RLY", 1, 2, 1001249, true, typeCodeOne, modeFerryList);
    _topologyDbContext.StopPoints.Add(stopPoint1);

    var stopPoint2 = new StopPoint("atco2", "commonName2", "indicator2", "stopLetter2", 2, "parentAtcoCode2",
        "ntc2", 3.3, 4.4, 2, false, typeCodeTwo, modeFerryAirList);
    _topologyDbContext.StopPoints.Add(stopPoint2);

    var stopPoint3 = new StopPoint("atco3", "commonName3", "indicator3", "stopLetter3", 3, "parentAtcoCode3",
        "discriminator3", 5.5, 6.6, 3, true, typeCodeThree, modeBusCoachList);
    _topologyDbContext.StopPoints.Add(stopPoint3);

    var stopPoint4 = new StopPoint("atco4", "commonName4", "indicator4", "stopLetter4", 4, "parentAtcoCode4",
        "discriminator4", 7.7, 8.8, 4, false, typeCodeFour, modeBusCoachList);
    _topologyDbContext.StopPoints.Add(stopPoint4);

    var stopPoint5 = new StopPoint("atco5", "commonName5", "indicator5", "stopLetter5", 5, "parentAtcoCode5",
        "discriminator5", 9.9, 10.1, 5, true, typeCodeFive, modeFerryList);
    _topologyDbContext.StopPoints.Add(stopPoint5);

    _topologyDbContext.SaveChanges();
}

测试用例情况

获取所有StopPoint的测试可以正常通过:

public async Task GetAllStopPoints_StopPointsInRepository_ReturnsAllStopPoints()
{
    // Act
    var allStopPoints = await _stopPointRepository.GetAllStopPoints();

    var firstStopPoint = allStopPoints.FirstOrDefault();

    // Assert
    allStopPoints.Count().Should().Be(5);
}

但按Mode过滤的测试无法通过,调试发现仅返回最后一个符合条件的实体(比如查询"BusCoach"时只返回StopPoint5,切换Mode后返回StopPoint4):

[Test]
public async Task GetByModeStopPointsRequestAsync_GivenListOfModes_ReturnsBusCoachStopPointsOnly()
{
    // Arrange
    var modes = new List<string> { "BusCoach" };

    // Act
    var result = await _stopPointRepository.GetStopPointsByModeAsync(modes);
    var firstSp = result.First();
    var secondSp = result.ElementAt(1);
    var thirdSp = result.ElementAt(2);
    var actual1 = firstSp.NaptanTypeCode.NaptanMode;
    var actual2 = secondSp.NaptanTypeCode.NaptanMode;
    var actual3 = thirdSp.NaptanTypeCode.NaptanMode;

    // Assert
    Assert.AreEqual(3, result.Count()); // 预期返回3个BusCoach类型的StopPoint
    Assert.That(actual1, Is.EqualTo("BusCoach"));
    Assert.That(actual2, Is.EqualTo("BusCoach"));
    Assert.That(actual3, Is.EqualTo("BusCoach"));
}

查询方法实现

public async Task<IEnumerable<StopPoint>> GetStopPointsByModeAsync(IEnumerable<string> modes)
{
    return  await _dbSet
        .AsNoTracking()
        .Include(i => i.NaptanTypeCode.NaptanTypeCodesModes)
        .Include(i => i.Modes)
        .Where(n => n.Modes.Any(m => modes.Contains(m.Name)))
        .ToListAsync();
}

这个方法和获取所有StopPoint的方法结构一致,只是多了按Mode过滤的Where条件。尝试过批量添加StopPoint和逐个添加,问题依旧;也曾用foreach手动筛选,同样失败。推测问题出在LINQ过滤逻辑上,导致仅返回最后一个实体。


内容的提问来源于stack exchange,提问作者SaHu07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:30:45