Почему этот экспресс LINQ возвращает подсписок только с одним элементом - PullRequest
4 голосов
/ 10 марта 2020

Вот моя объектная модель.

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

База данных содержит Элементы и LineItems таблицы, соответствующие объектной модели. Я использую приведенное ниже выражение LINQ для извлечения объекта ItemViewModel при условии ИД элемента.

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.

1 Ответ

2 голосов
/ 11 марта 2020

Как подсказывает Иван Стоев в комментариях к этому вопросу, причина заключается в ошибке в Entity Framework Core, когда он имеет дело с бесключевыми сущностями как дочерней сущностью. Я проверил это на собственном опыте, добавив первичный ключ в мою предыдущую таблицу ключей, а затем проверил тот же оператор LINQ. После добавления первичного ключа он начинает выдавать мне список из 3 элементов, а не только 1. Поэтому после этого вопроса и моего тестирования я сообщил об этом на EF Core tracker tracker .

* 1006. * Для тех, кто сталкивается с этим вопросом в поисках ответа, у нас есть два варианта. Либо добавьте первичный ключ в вашу таблицу ключей, либо определите составной первичный ключ в вашей модели сущности EF. Я исправил свою ситуацию, используя следующую строку:
modelBuilder.Entity<LineItem>().HasKey(i => new { i.ItemId, i.Name });

Это работает, потому что комбинация LineItem.ItemId и LineItem.Name уникальна для моих сущностей. Благодарность за этот ответ идет на ответ (хотя и не официально принятый ответ) на более ранний вопрос SO.

...