为什么这个 LINQ 表达式 [=第 10 个子列表只有一个项目

Why this LINQ expressoin returns the sublist with only one item

这是我的对象模型。

public class ItemViewModel
{
    public Item ItemObject { get; set; }
    public IEnumerable<LineItem> Fields { get; set; } = new List<LineItem>();
}

public class Item
{
    public int ItemId { get; set; }
    public DateTime DatePurchased { get; set; }
}

public class LineItem
{
    public int ItemId { get; set; }
    public string Name { get; set; }
}

数据库包含ItemsLineItemstables,对应对象模型。我正在使用下面编写的 LINQ 表达式来检索一个 ItemViewModel 对象,提供一个项目 ID。

var i = from i in _dbContext.Items
        where i.ItemId == 123
        select new ItemViewModel
        {
            ItemObject = i,
            Fields = from field in _dbContext.LineItems
                     where field.ItemId == i.ItemId
                     select field
        };            
var viewModel = await i.SingleOrDefaultAsync();

代码编译正常,但执行后 viewModel.Fields 属性 仅包含一个列表项,而数据库 table 中有三个针对 ItemID:123 的行项.

此代码段生成的 SQL(通过 SQL Profiler 捕获)returns 三个行项目,通过 LEFT JOIN。这意味着生成的 SQL 没问题,但 Entity Framework 出现问题,但我不知道是什么?

更新: 这是生成的 SQL 查询,它正确地给出了三行:

SELECT 
    [t].[ItemId], [t].[DatePurchased], 
    [s0].[ItemId], [s0].[Name]
FROM 
    (
    SELECT 
        TOP(2) [s].[ItemId], [s].[DatePurchased]
    FROM 
        [Items] AS [s]
    WHERE 
        [s].[ItemId] = 123
    ) AS [t]
LEFT JOIN [LineItems] AS [s0] ON [t].[ItemId] = [s0].[ItemId]
ORDER BY [t].[ItemId]

技术堆栈是 .NET Core 3.1 和 Entity Framework Core。

正如 Ivan Stoev 在此问题下的评论中所建议的那样,原因是 Entity Framework 核心中的错误,将无键实体作为子实体处理时。我通过向我之前的无密钥 table 添加一个主键,然后验证相同的 LINQ 语句,对其进行了第一手测试。添加主键后,它开始给我一个包含 3 个项目的列表,而不仅仅是 1 个。所以在这个问题和我的测试之后,我已经将它报告给 EF Core issue tracker

对于任何在寻找答案时偶然发现这个问题的人,我们这里有两个选择。将主键添加到无键 table 或在 EF 实体模型中定义复合主键。我使用以下行修复了我的情况:

modelBuilder.Entity<LineItem>().HasKey(i => new { i.ItemId, i.Name });

之所以有效,是因为 LineItem.ItemIdLineItem.Name 组合对于我的实体来说是独一无二的。此答案归功于 an answer(尽管未被正式接受的答案)对较早的 SO 问题。