One To Many возвращает пустой массив (решено) - PullRequest
3 голосов
/ 02 марта 2020

Я пытаюсь соединить два объекта с отношением один-ко-многим, рабочее место может содержать несколько людей, а одно лицо может иметь только одно рабочее место.

Когда я выполняю этот фрагмент кода и проверяю, чтобы увидеть В результате p1 правильно назначил w1 как p1.Workplace, но список людей из w1.employees всегда пуст.

Нужно ли вручную добавлять p1 в w1.Employees даже после того, как я назначил w1 для p1.Workplace?

SeedData.cs (фрагмент кода)

var w1 = new Workplace
{
   EntryCode = "1111"
   //[...] other data I cut out for brievity
};
context.Workplaces.Add(w1);

Person p1 = new Person
{
    Name = "Spencer",
    Workplace = w1
   //[...] other data I cut out for brievity
};
context.Person.Add(p1)
context.SaveChanges();

Workplace.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Counsel.Models
{
    [Table("Workplace")]
    public class Workplace
    {
        [Column("WorkplaceId")]
        public int WorkplaceId {get;set;}

        [Column("EntryCode")]
        public string EntryCode {get;set;}

        [Column("ConfirmationCode")]
        public string ConfirmationCode {get;set;}

        [Column("Employees")]
        public ICollection<Person> Employees {get;set;}
    }
}

Person.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Counsel.Models
{
    public class Person
    {
        [Column("PersonId")]
        public int PersonId {get;set;}

        [Column("Image")]
        public string Image {get;set;}

        [Column("FName")]
        public string FName { get; set; }

        [Column("LName")]
        public string LName {get;set;}

        [Column("Role")]
        public string Role {get;set;}

        [Column("Email")]
        public string Email {get;set;}

        [Column("Password")]
        public string Password {get;set;}

        public Workplace Workplace {get;set;} = new Workplace();
        public ICollection<ChatPerson> Chats {get;set;}
    }
}

DataContext.cs

using Counsel.Models;
using Microsoft.EntityFrameworkCore;

namespace Counsel.Models {
    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions<DataContext> opts): base(opts){}

        public DbSet<Person> People {get;set;}
        public DbSet<Workplace> Workplaces {get;set;}


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Person>((item)=>{
                item.HasKey(p => p.PersonId);
                item.HasOne<Workplace>(p => p.Workplace).WithMany(w => w.Employees).OnDelete(DeleteBehavior.SetNull);
            });


            modelBuilder.Entity<Workplace>((item)=>{
                item.HasKey(p => p.WorkplaceId);
                item.HasMany<Person>(w => w.Employees).WithOne(p => p.Workplace).OnDelete(DeleteBehavior.Cascade);
            });
        }
    }
}

WorkplaceController.cs (фрагмент кода)

[HttpGet("{id}")]
        public Workplace GetWorkplace(int id)
        {
           return context.Workplaces
                .Where(c => c.WorkplaceId == id)
                .Include(c => c.Employees).ThenInclude(c => c.Workplace)
                .FirstOrDefault();

        }

GetWorplace () вывод

[
  {
    "workplaceId": 1,
    "entryCode": "1111",
    "confirmationCode": "1111",
    "employees": [

    ]
  }
]

Как видите, массив «employee» пуст, хотя там должен быть и p1.

Ответы [ 3 ]

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

Проблема вызвана инициализатором свойств навигации reference :

public Workplace Workplace { get; set; } = new Workplace(); // <--

Никогда этого не делать - это приводит к путанице в исправлении свойств навигации EF и приводит к непредвиденным поведениям во время выполнения.

Обратите внимание, что инициализация collection свойств навигации в порядке, но не обязательна. Это связано с тем, что null в свойстве ссылочной навигации имеет особое значение и действительно предоставляет ссылку на главную сущность, которая может содержать или не содержать коллекцию зависимых сущностей.

Вскоре удалите инициализатор

public Workplace Workplace { get; set; }

и проблема будет решена.

1 голос
/ 02 марта 2020

Если вы используете ленивую загрузку данных, вам нужно перечислить данные, чтобы их можно было включить в контекст EF. Дочерние элементы не извлекаются по умолчанию. Другая вещь, которую вы можете сделать, это явно включить потомков при построении запроса. Здесь вы можете увидеть, как работает операция включения: https://entityframework.net/include-multiple-levels

И вы также можете увидеть связанную с этим проблему здесь: Включить детей в EF

0 голосов
/ 02 марта 2020

Workplace имеет свойство отношения Employees, но оно отображается [Column("Employees")], которое, как я предполагаю, заставляет EF перестать рассматривать его как отношение для поиска других объектов и начинает обрабатывать его как столбец, который существует в таблице Workplace. Удалите атрибут столбца и, если необходимо, предоставьте EF дополнительную информацию, чтобы он мог правильно отобразить отношение Персона * ↔ 1 на рабочем месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...