#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);
Я суммировал пару веских причин, по которым код не должен возвращать объекты в представление здесь.