Sto creando un'applicazione che deve supportare più di una lingua.
Pertanto, alcuni dei record nel mio database devono avere più versioni per ogni lingua.
Spiegherò innanzitutto come ottengo questo obiettivo: considera un'entità chiamata Region
che rappresenta una posizione geografica e ha semplicemente un nome.
Progetterei le mie entità in questo modo:
public class Region
{
public int Id { get; set; }
public List<RegionLanguage> Languages { get;set; }
}
public class RegionLanguage
{
public Region Region { get;set; } // Parent record this language applies to
public string CultureCode { get; set; } // Will store culture code such as en-US or fr-CA
// This column/property will be in the language specified by Culturecode
[StringLength(255)]
public string Name { get;set; }
}
Dal punto di vista del database, funziona alla grande perché è scalabile all'infinito su qualsiasi numero di record. Tuttavia, a causa del modo in cui Entity Framework Core funziona, diventa meno scalabile.
Utilizzando la struttura sopra, posso eseguire una query su una Region
e generare un modello di visualizzazione basato su informazioni di cultura specifiche:
var region = _context.Regions.Where(e => e.Id == 34)
.Include(e => e.Languages)
.FirstOrDefault();
var viewModel = new RegionViewModel
{
Name = region.Languages.FirstOrDefault(e => e.CultureCode == "en-US")?.Name // en-US would be dynamic based on the user's current language preference
}
Puoi vedere che questo diventa inefficiente poiché devo includere TUTTI i record di lingua per l'entità che sto recuperando, quando in realtà ne ho solo bisogno e poi cerco la lingua corretta in memoria. Certamente questo peggiora ancora quando devo recuperare un elenco di Regions
che deve quindi restituire una grande quantità di dati non necessari.
Naturalmente, questo è possibile utilizzando SQL direttamente semplicemente aggiungendo una clausola aggiuntiva sull'istruzione join
:
select *
from Regions
left join RegionLanguage on (RegionLanguage.Region = Regions.Id and RegionLanguage.CultureCode = 'en-US')
Tuttavia, a mio RawQuery
, questo non è possibile fare in modo nativo da Entity Framework Core senza utilizzare un RawQuery
( EF: Includi con clausola where )
Ciò pone la domanda: esiste un modo migliore per ottenere record multilingue nel database utilizzando EF Core? O dovrei semplicemente continuare con il mio approccio e sperare che EF Core implementa Include
filtro prima che la mia applicazione ne abbia effettivamente bisogno (ammetto che potrei essere leggermente ottimizzato prematuramente, ma sono sinceramente curioso se esiste un modo migliore per raggiungere Questo).
È possibile utilizzare un filtro di query globale
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<RegionLanguage>(builder =>
{
builder.HasQueryFilter(rl => rl.CultureCode == "en-US");
});
}