Entity Framework Core 2.0 Select Query с проблемой «многие ко многим» - PullRequest
0 голосов
/ 19 сентября 2018

Ниже приведена модель.

class Product
{
    public int Id { get; set; }
    public ICollection<Categorization> Categorization { get; set; }
}

class Categorization
{
    public int ProductId { get; set; }
    public Product Product { get; set; }

    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

class Category
{
    public int Id { get; set; }
    public ICollection<Categorization> Categorization { get; set; }
}

Я пытаюсь перечислить все продукты и их категории.Код API, как показано ниже

foreach (var product in _context.Products.ToList()){
    var categories = product.Categorization.Select(c => c.Category);
    ...     
}

Когда мы вызываем API, я получаю эту ошибку:

System.ArgumentNullException: значение не может быть нулевым.
Имя параметра: источник
at System.Linq.Enumerable.Select [TSource, TResult] (IEnumerable 1 source, Func 2 селектор)

Ответы [ 4 ]

0 голосов
/ 20 сентября 2018

Для запроса всех продуктов и их категорий, вы можете попробовать Include и ThenInclude, как показано ниже:

        public async Task<IActionResult> GetAllArticleAsync()
    {
        var articles = await _context.Articles
                               .Include(a => a.ArticleTags)
                               .ThenInclude(at => at.Tag)
                               .Select(a => new
                               {
                                   Id = a.Id,
                                   ArticleName = a.ArticleName,
                                   Tags = a.ArticleTags.Select(at => at.Tag).ToList()
                               })
                               .ToListAsync();
        return Ok(articles);
    }

Для этого вам необходимо настроить opt.SerializerSettings.ReferenceLoopHandling в Startup.cs, как показано ниже:

        services.AddMvc()
                .AddJsonOptions(opt => opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Для полной демонстрации см. EFCorePro

0 голосов
/ 19 сентября 2018

Попробуйте добавить виртуальный объект, например:

class Product
{
    public int Id { get; set; }
    public virtual ICollection<Categorization> Categorization { get; set; }
}

class Categorization
{
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }

    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }
}

class Category
{
    public int Id { get; set; }
    public virtual ICollection<Categorization> Categorization { get; set; }
}
0 голосов
/ 19 сентября 2018

Ошибка возникает из-за того, что product.Categorization является нулевым.
Ленивая загрузка поддерживается в Entity Framework Core 2.1 и выше.Пожалуйста, проверьте, что Категоризация для определенного продукта не является нулевой, и попробуйте выполнить энергичную загрузку (хотя это может не потребоваться в соответствии с документацией). Например:

foreach (var product in _context.Products.Include(p => p.Categorization).ToList()){
    if (product.Categorization != null) {
        var categories = product.Categorization.Include(c => c.Category).Select(c => c.Category);
        ...     
    }
}

Также убедитесь, что вы настроили множество-ко-многим правильно, так как для этого необходимо определить составной первичный ключ следующим образом:

override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Categorization>().HasKey(c => new { c.ProductId, c.CategoryId});
}

Пожалуйста, проверьте этот учебник, так как он может быть полезен: Учебник Entity Framework - Настройка Many-to-Многие отношения

0 голосов
/ 19 сентября 2018

product.Categorization - ноль, потому что он не загружен.Если вы ожидаете, что ленивая загрузка справится с нагрузкой, вы должны сделать свойство product.Categorization виртуальным (вместе со свойствами, которые вы хотите ленивую загрузку в классе Categorization, в данном случае Category)

Изменить: в вашем примере вы должны стремиться загрузить данные, используя Include и ThenInclude, поскольку вы знаете, что вам нужны данные:

_context.Products
   .Include( p => p.Categorization )
   .ThenInclude( c => c.Category )
   .ToList()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...