Проблема с использованием связанных объектов в «database-first»

#c# #entity-framework #ef-database-first

#c# #entity-framework #ef-database-first

Вопрос:

Я изучаю MVC и для этого разрабатываю «умный форум». Я создал базу данных, но у меня возникла некоторая проблема с объектами. Я должен выполнить эту команду

  "Scaffold-DbContext "Server=(localdb)mssqllocaldb;Database=SmartForum;Trusted_Connection=True; Microsoft.EntityFrameworkCore.SqlServer -OutputDir ModelsFromDb" ,
  

Фрагмент кода:

 modelBuilder.Entity<ArgomentiPerArea>(entity =>
            {
                entity.HasKey(e => e.ArgomentoId);

                entity.Property(e => e.ArgomentoId).HasColumnName("argomentoId");

                entity.Property(e => e.Archiviato).HasColumnName("archiviato");

                entity.Property(e => e.AreaId).HasColumnName("areaId");

                entity.Property(e => e.ModeratoreId).HasColumnName("moderatoreId");

                entity.Property(e => e.NomeArgomento).HasColumnName("nome_argomento");

                entity.Property(e => e.NumeroRigaPerArea).HasColumnName("numero_riga_per_area");

                entity.Property(e => e.TestoPerArgomento).HasColumnName("testo_per_argomento");

                entity.HasOne(d => d.Area)
                    .WithMany(p => p.ArgomentiPerArea)
                    .HasForeignKey(d => d.AreaId)
                    .HasConstraintName("FK_ArgomentiPerArea_Aree");

                entity.HasOne(d => d.Moderatore)
                    .WithMany(p => p.ArgomentiPerArea)
                    .HasForeignKey(d => d.ModeratoreId)
                    .HasConstraintName("FK_ArgomentiPerArea_Moderatori");
            });
  

второй фрагмент :

 public partial class ArgomentiPerArea
    {
        public ArgomentiPerArea()
        {
            Thread = new HashSet<Thread>();
        }
        [Key]
        public int ArgomentoId { get; set; }
        public string NomeArgomento { get; set; }
        public int? AreaId { get; set; }
        public bool? Archiviato { get; set; }
        public int? NumeroRigaPerArea { get; set; }
        public string TestoPerArgomento { get; set; }
        public int? ModeratoreId { get; set; }

        public virtual Aree Area { get; set; }
        public virtual Moderatori Moderatore { get; set; }
        public virtual ICollection<Thread> Thread { get; set; }

    }

public partial class Aree
    {
        public Aree()
        {
            ArgomentiPerArea = new HashSet<ArgomentiPerArea>();
        }
        [Key]
        public int AreaId { get; set; }
        public string NomeArea { get; set; }
        public int? NumeroRiga { get; set; }
        public int? NumeroColonna { get; set; }

        public virtual ICollection<ArgomentiPerArea> ArgomentiPerArea { get; set; }
    }

public partial class Moderatori
    {
        public Moderatori()
        {
            ArgomentiPerArea = new HashSet<ArgomentiPerArea>();
            SegnalazioniPerModeratori = new HashSet<SegnalazioniPerModeratori>();
        }
        [Key]
        public int ModeratoreId { get; set; }
        public string UsernameModeratore { get; set; }
        public string PasswordHash { get; set; }
        public string NomeCognome { get; set; }
        public bool? Archiviato { get; set; }

        public virtual ICollection<ArgomentiPerArea> ArgomentiPerArea { get; set; }
        public virtual ICollection<SegnalazioniPerModeratori> SegnalazioniPerModeratori { get; set; }
    }
  

при запуске этого кода

 public class ArgomentiPerAreasController : Controller
    {
        private ModelsFromDb.SmartForumContext db = new ModelsFromDb.SmartForumContext();

        // GET: ArgomentiPerAreas
        public ActionResult Index()
        {
            var argomentiPerAreas = db.ArgomentiPerArea.Include(a => a.Area).Include(a => a.Moderatore);            

            string msg = "m";
            return View(argomentiPerAreas.ToList());
        }

.............
.............}
  

Я проверяю в представлении, и «модератор» и «область» имеют нулевое значение.
Я не понимаю, но я знаю database first и MVC поверхностно. Я надеюсь на некоторые предложения.

Комментарии:

1. asp.net-mvc не имеет ничего общего с Entity Framework.

2. данные возвращаются для просмотра

Ответ №1:

Вероятно, это связано с циклическими ссылками между вашими аргументами * и модератором / областью. Область хранит коллекцию обратно в Argomenti *, поэтому, когда MVC переходит к сериализации корневого объекта (Argomenti), он сталкивается с областью, затем выполняет итерацию по области, коллекции Argomenti * и т. Д. Цикл продолжается. Он выходит из строя и не пытается сериализовать циклические зависимости.

Как правило, лучшее, что можно сделать с EF и представлениями, — это не пытаться отправлять объекты в представление. Вместо этого создайте модель представления POCO (обычный старый объект C #) для отправки в представление. Эта модель представления содержит только поля, необходимые для представления, и ваш запрос EF использует .Select() для заполнения этой модели представления. Это позволяет избежать всей проблемы с циклическими ссылками и сводит на нет необходимость преднамеренной ускоренной загрузки ( .Include() ) или риск для производительности при отложенной загрузке.

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

 [Serializable]
public class ArgumentiViewModel
{
    public string NomeArgomento { get; set; }
    public bool? Archiviato { get; set; }
    public int? NumeroRigaPerArea { get; set; }
    public string TestoPerArgomento { get; set; }
    public string NomeArea { get; set; } // From Area
    public string NomeCognome { get; set; } // From Moderator
}
  

Затем, когда я хочу вернуть это в представление:

 var argomentiViewModels = db.ArgomentiPerArea
    .Select(x => new ArgomentiViewModel
    {
        NomeArgomento = x.NomeArgomento,
        Archiviato - x.Archiviato,
        NumeroRigaPerArea = x.NumeroRigaPerArea,
        TestoPerArgomento = x.TestoPerArgomento,
        NomeArea = x.Area.NomeArea, // From Area
        NomeCognome = x.Moderatori.NomeCognome // From Moderator
    }).ToList();

string msg = "m";
return View(argomentiViewModels);
  

Я суммировал пару веских причин, по которым код не должен возвращать объекты в представление здесь.