简体   繁体   中英

Translatable models with Entity Framework Core

I am migrating my php application to a .net core application using Entity Framework Core.

Several of my models have translations linked to them from the translations table. The way the models are linked to the translations is by modelname and modelid . The modelname is the name of the class and the id is the id of that object. Keep in mind, an object can have multiple translations with a unique slug.
I was wondering if it is possible to easily implement this using entity framework. So the models are linked by their id, but also filtered on their own class name. Will I have to create this relation in fluent api for every model or is there a better solution for this?

Below is a small example of how the database looks like. But in the real database, there are many more tables that have translations. The database can, of course, be modified if needed.

在此处输入图片说明

It seems that you want to achieve polymorphic association with TPC strategy.

Unfortunately current version of EF Core 2.0 does not support TPC and feature is planned for release in EF Core 2.1 - https://github.com/aspnet/EntityFrameworkCore/wiki/Roadmap

This is the solution that works with EF 6.0:

public class Context : DbContext
{

    public Context() : base()
    {

    }

    public IDbSet<Translation> Translations { get; set; }

    public IDbSet<TranslatedModel> TranslationModels { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Store>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("Stores");
            });

        modelBuilder.Entity<Publisher>().Map(m =>
            {
                m.MapInheritedProperties();
                m.ToTable("Publishers");
            });

        modelBuilder.Entity<Translation>()
            .HasRequired(t => t.TranslatedModel)
            .WithRequiredDependent(t => t.Translation);
    }
}

public class Translation
{
    public int Id { get; set; }

    public string Value { get; set; }

    public TranslatedModel TranslatedModel { get; set; }
}

public abstract class TranslatedModel
{
    public int Id { get; set; }

    public Translation Translation { get; set; }
}

public class Store : TranslatedModel
{
    public int Website { get; set; }

}

public class Publisher : TranslatedModel
{
    public string Website { get; set; }
}

Problem here is that you may have the same ids for Products and Stores, resulting in clashes. So I would recommend instead of having model_id and model_name as reference key, just change your ids type from int to GUID and drop the model_name.

more info here:

https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines

What I know that EF DOES offer that might help is that EF offers polymorphism based off of conditions. You could implement a Model class using "Translations" as the table base, have Products/Stores/Publishers inherit from Model, and define the condition upon which a Product/Store/Publisher is instantiated be based off the "model_name" field.

I'm not entirely sure, but in the child classes, you may be able to define those navigator properties as only relevant to one type.

Here is the guide:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application

The solution I used to solve this is adding a new table, Translatables . every table that is translatable now has a field translatable_id and all translations are linked to a Translatable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM