Qualcuno può dirmi perché le entità Article
correlate non vengono caricate su .Include(a => a.Article)
? Sono sempre NULL
anche se ArticleId
ha davvero un valore. La relazione tra FrontPageItem
e l' Article
è 1-0..1. Un Article
può esistere senza alcuna connessione a un FrontPageItem
, ma un FrontPageItem
deve avere un Article
.
In una soluzione piuttosto brutto, ho fatto ricorso a foreach
-ing attraverso tutti gli oggetti restituiti nella lista e aggiungendo Article
manualmente, come si può vedere nel mio indice metodo seguito.
public async Task<IActionResult> Index()
{
List<FrontPageItem> items = await db.FrontPageItems
.Include(a => a.Article)
.ThenInclude(c => c.CreatedBy)
.ThenInclude(m => m.Member)
.Include(a => a.Article)
.ThenInclude(e => e.EditedBy)
.ThenInclude(m => m.Member)
.Include(a => a.Article)
.ThenInclude(e => e.PublishReadyBy)
.ThenInclude(m => m.Member)
.Include(p => p.WebPage)
.OrderByDescending(o => o.DatePublished)
.ToListAsync();
// I don't want to foreach, but without it, Article is always NULL for all items.
foreach (FrontPageItem item in items)
{
item.Article = await db.Articles
.Where(a => a.Id == item.ArticleId).FirstOrDefaultAsync();
}
List<FrontPageItemViewModel> vm =
auto.Map<List<FrontPageItemViewModel>>(items);
return View(vm);
}
Questi sono i modelli:
public class FrontPageItem
{
public int Id { get; set; }
// ... some more properties
public int? ArticleId { get; set; }
public Article Article { get; set; }
public AdminUser CreatedBy { get; set; }
public AdminUser EditedBy { get; set; }
public AdminUser PublishedBy { get; set; }
}
public class Article
{
public int Id { get; set; }
// ... some more properties
public int? FrontPageItemId { get; set; }
public FrontPageItem FrontPageItem { get; set; }
public AdminUser CreatedBy { get; set; }
public AdminUser EditedBy { get; set; }
public AdminUser PublishReadyBy { get; set; }
}
public class AdminUser
{
public int Id { get; set; }
// ... some more properties
public int MemberId { get; set; }
public Member Member { get; set; }
}
public class Member
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// ... some more properties
public AdminUser AdminUser { get; set; }
}
Questo è il modellista:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Article>()
.HasOne(p => p.FrontPageItem)
.WithOne(i => i.Article)
.HasForeignKey<Article>(b => b.FrontPageItemId);
}
Innanzitutto è necessario conoscere Caricamento ansioso, Caricamento lento, Caricamento esplicito
Caricamento desideroso
Il caricamento desideroso ti aiuta a caricare tutte le entità necessarie contemporaneamente; cioè, tutte le entità secondarie verranno caricate in una singola chiamata al database. Ciò può essere ottenuto utilizzando il metodo Include, che ritrasforma le entità correlate come parte della query e viene caricata una grande quantità di dati contemporaneamente.
Caricamento pigro
È il comportamento predefinito di un Entity Framework, in cui un'entità figlio viene caricata solo quando vi si accede per la prima volta. Ritarda semplicemente il caricamento dei dati correlati, fino a quando non lo chiedi.
Caricamento esplicito
Esistono opzioni per disabilitare il caricamento lento in un Entity Framework. Dopo aver disattivato il caricamento lento, è comunque possibile caricare le entità chiamando esplicitamente il metodo Load per le entità correlate. Esistono due modi per utilizzare il metodo Load Reference (per caricare una singola proprietà di navigazione) e Collection (per caricare le raccolte)
Quindi per caricare un'entità relazionale è possibile utilizzare il pacchetto Microsoft.EntityFrameworkCore.Proxies per abilitare il caricamento lento. Pertanto, quando si esegue una query sul database, EF restituirà la base di dati relazionale sulla loro relazione
Il mio codice di esempio è simile al seguente
services.AddDbContextPool<ApplicationDbContext>(options =>
options.UseLazyLoadingProxies().UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("AwesomeCMSCore")).UseOpenIddict());
Per favore fatemi sapere se avete qualche problema