Je teste donc Entity Framework Core et rencontre des difficultés avec ma première paire de modèles relationnels. J'essaie d'utiliser des conventions pour former la relation, comme suit:
L'entité principale, avec la clé principale conventionnelle (Id) et la propriété de navigation de la collection (la liste des emplacements):
public class Site
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public int LocationCount { get; set; } = 1;
public List<Location> Locations { get; set; } = new List<Location>();
}
L'entité dépendante, avec la clé étrangère conventionnelle (SiteId) et la propriété de navigation de référence (Site):
public class Location
{
public int Id { get; set; }
public int SiteId { get; set; }
public Site Site { get; set; }
public int AreaCount { get; set; } = 1;
public Location(Site site) { SiteId = site.Id; }
}
Et comme je veux que chaque site ait déjà au moins un emplacement, je l'ai mis dans l'action Créer du SiteController, afin de créer les personnes à charge avec le principal:
[HttpPost]
public IActionResult Create(Site site)
{
_context.Sites.Add(site);
for (int i = 0; i < site.LocationCount; i++)
_context.Locations.Add(new Location(site));
_context.SaveChanges();
return RedirectToAction("Details", new { Name = site.Name });
}
Cependant, dans la vue Détails, lorsque j'essaie d'afficher les emplacements créés, la liste est toujours vide:
<h2>@Model.Locations.Count Locations</h2>
@foreach (Location l in Model.Locations)
{
<div class="row">
<div class="col-sm-12">@l.Id</div>
</div>
}
Juste résultats en:
0 Locations
Merci d'avance pour toute aide expliquant ce que j'ai manqué!
Éditer: à la demande, voici le corps de l'action Détails dans le contrôleur de site, qui récupère les données de modèle pour la vue Détails:
public IActionResult Details(string name)
{
var model = _context.Sites.FirstOrDefault(a => a.Name == name);
if (model == null) model = new Site();
return View(model);
}
Aussi, par une suggestion, j'ai résolu le problème de la définition de Location.SiteId avant que Site.Id ait une valeur, puisque l'identifiant n'est généré automatiquement sur le site qu'après l'appel de SaveChanges (). Malheureusement, le résultat (liste d'emplacements vide) est toujours le même:
[HttpPost]
public IActionResult Create(Site site)
{
int nextsiteid = _context.Sites.Count() + 1;
_context.Sites.Add(site);
for (int i = 0; i < site.LocationCount; i++)
_context.Locations.Add(new Location(siteid));
_context.SaveChanges();
return RedirectToAction("Details", new { Name = site.Name });
}
Et changé le constructeur Location pour utiliser l'Id à la place de l'instance:
public Location(int siteid) { SiteId = siteid; }
Merci d'avance pour toute suggestion supplémentaire!
Je ne fais que transcrire la réponse qui m'a été fournie, qui a été fournie dans les commentaires du message original, afin que tout lecteur puisse facilement le trouver.
Le problème était tout simplement que EF Core ne prend pas encore en charge le chargement paresseux. Ainsi, lorsque l'entité Site est remplie, elle ne charge pas paresseusement la liste des emplacements dépendants dans la propriété de navigation de la collection.
Le correctif consiste à utiliser un chargement rapide, par le biais de:
var model = _context.Sites.Include(s => s.Locations).FirstOrDefault(a => a.Name == name);
Lors du chargement des données de modèle du site à fournir à la vue.
Merci pour la solution, Ivan!
si le chargement paresseux est vrai. Pas besoin de faire une boucle ou de naviguer son enfant. sa sauvera votre parent et son enfant. assurez-vous que vous obtenez les parents et son enfant
[HttpPost]
public IActionResult Create(Site site)
{ // debug here are you getting parent & its child ?
_context.Sites.Add(site);
// for (int i = 0; i < site.LocationCount; i++) // No need of it
// _context.Locations.Add(new Location(site)); // No need of it
_context.SaveChanges();
return RedirectToAction("Details", new { Name = site.Name });
}
Mise à jour: si ces deux tables sont liées et que vous essayez d'ajouter manuellement une table d'emplacement. Laissez-moi vous donner un simple, espérons que cela vous aidera
[HttpPost]
public IActionResult Create(Site site)
{ // debug here are you getting parent & its child ?
_context.Sites.Add(site);
// get the last added site id
int? maxId=
_context.Sites.orderbyDecending(x=>x.SiteId).FirstorDefault(x=>x.SiteId);// may be in this line typing mistake , you change it according to linq
foreach(var i in site.Location)
{
// in this loop traverse the child array and override the foreign key id with last added id
i.SiteId =maxId;
_context.Locations.Add(i);
}
_context.SaveChanges();
return RedirectToAction("Details", new { Name = site.Name });
}