我正在学习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());
}
.............
.............}
我签入视图,并且“ moderatore”和“ area”的值为空。 我不明白,但我首先了解数据库,但对MVC还是很肤浅。我希望有一些建议。
答案 0 :(得分:1)
这可能是由于Argomenti *和主持人/区域之间的循环引用。区域会将集合保留回Argomenti *,因此当MVC序列化根实体(Argomenti)时,它会跨区域,然后遍历该区域,生成Argomenti *的集合,然后循环。它可以解决问题,并且不会尝试序列化循环依赖性。
通常,与EF和视图相关的最好的事情是 not 尝试将实体发送到视图。而是创建一个POCO(普通的旧C#对象)视图模型以发送到该视图。该视图模型仅包含视图所需的字段,并且您的EF查询使用.Select()
填充该视图模型。这样可以避免整个循环引用问题,并且不需要故意进行急切加载(.Include()
)或懒加载的性能风险。
例如:如果我想要一个Argumenti列表,并且想要显示每个区域和主持人作为其一部分:
[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);
我总结了代码为什么不应该将实体返回视图here的两个很好的理由。