c# - 为什么此 LINQ 表达式返回只有一项的子列表

标签 c# linq-to-sql entity-framework-core

这是我的对象模型。

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

数据库包含 商品 订单项 表,对应于对象模型。我正在使用下面编写的 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属性仅包含一个列表项,而在数据库表中针对 ItemID:123 有三个行项。

此代码段生成的 SQL(通过 SQL Profiler 捕获)通过 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 Core 中的一个错误,当将无键实体作为子实体处理时。我通过向我早期的无键表添加主键,然后验证相同的 LINQ 语句来第一手测试它。添加主键后,它开始给我一个包含 3 个项目的列表,而不是只有 1 个。所以在这个问题和我的测试之后,我已将其报告给 EF Core issue tracker .

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

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

它有效是因为 LineItem.ItemIdLineItem.Name组合对我的实体来说是独一无二的。此答案归功于 an answer (虽然没有正式接受答案)早先的 SO 问题。

关于c# - 为什么此 LINQ 表达式返回只有一项的子列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60610934/

相关文章:

linq - 使用 Moq 进行单元测试有时会在 ToListAsync() 上失败

从签名文件中获取 SignedCms 的 C# 实现

c# - 如何摆脱 Visual Studio 2010 中烦人的代码提示?

c# - 获取从 UITableView 中选择的行?

linq - LINQ 的 NOT IN 子句?

c# - 如何指定Entity Framework核心表映射?

c# - OnModelCreating 的目的 - EF Core 数据库优先方法

c# - 使用 Visual Studio 在代码中查找可等待的方法

linq-to-sql - 团结 : passing in a new datacontext each time?

linq - 将 LINQ 查询绑定(bind)到 DataGridView