Search code examples
.netentity-framework-coretranslation

How can I effectively model Translatable Properties in EF Core?


I am building an application on .NET 5 using Entity Framework Core and PostgreSQL. In the database, I have several entities that contain string properties that should be translatable to different languages.

My current approach is:

public class TString
    {
        public int Id { get; set; }
        
        /// <summary>
        /// The string value = Default Value
        /// </summary>
        public string Text { get; set; }
        
        public virtual ICollection<Translation> Translations { get; set; }

        /// <summary>
        /// Returns the translation for a given language or the default value.
        /// </summary>
        /// <param name="language"></param>
        /// <returns></returns>
        public string Get(string language)
        {
            if (Translations.Any(t => t.Language == language))
                return Translations.First(t => t.Language == language).Text;
            return Text;
        }
   }

    public class Translation
    {
        public int Id { get; set; }
        
        public int TStringId { get; set; }
        public virtual TString TString { get; set; }
        public string Language { get; set; }
        public string Text { get; set; }
    }

and with an example usage like:

    public class Product
    {
        public int Id { get; set; }
        
        public int NameId { get; set; }
        
        public virtual TString Name { get; set; }
  
        [...]
    }

The approach above works, but seems very unelegant to me since when querying, it is always necessary to use .Include(x => x.Name).ThenInlude(n => n.Translations) Since there is no way to tell EF Core to load a property by default unless you are using Owned Types (which is not an option because then you cannot query using the TString Id), is there any better way of doing this?


Solution

  • Since there is no way to tell EF Core to load a property by default unless you are using Owned Types

    Actually there is - starting from EF Core 5.0, by configuring navigation properties using the AutoInclude fluent API, like

    modelBuilder.Entity<Product>()
        .Navigation(e => e.Name)
        .AutoInclude();
    
    modelBuilder.Entity<TString>()
        .Navigation(e => e.Translations)
        .AutoInclude();