本文介绍了在Entity Framework Core中使用两列的一对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我有一个表 Translation ,该表可以包含任何模型的翻译。为此,该表具有两个字段: Model ModelId Model 属性包含一个指示模型类型的整数,而 ModelId 具有此模型的ID。

例如: Product 表的模型类型ID为 1 。要获取ID为 317 的产品的所有翻译,我搜索 Model = 1和ModelId = 317 的翻译。

In my project I have a table Translation that can have translations for any model. To achieve this, the table has two fields: Model and ModelId. The Model property holds an integer indicating the type of the model and the ModelId has the id of this model.
So, for example: the Product table has modeltype id 1. To get all translations for a product with id 317, I search for translations with Model=1 AND ModelId=317.

现在,我想在Entity Framework Core中创建此关系。我所有的模型都从类 BaseModel 继承,该类具有属性 ModelType ,其中包含模型类型的ID。此字段未映射,因此在数据库中不可用。

Now I would like to create this relation in Entity Framework Core. All my models inherit from the class BaseModel that has a property ModelType holding the id of the model type. This field is not mapped, so it is not available in the database.

我尝试使用流利的api创建关系,但不允许我指定

I have tried to create the relation using fluent api, but it doesn't allow me to specify more columns to filter on.

modelBuilder.Entity<BaseModel>()
    .HasMany<Translation>(bm => bm.Translations)
    // Extra filters

有什么方法可以创建这个关系,而不必为每个需要翻译的查询手动创建联接?

Is there any way to create this relation without having to manually create a join for every query that requires translations?

推荐答案

因为 modelBuilder.Entity< ; BaseModel>()将使用 TPH 继承方法,我假设您没有使用EF代码优先方法来创建数据库,而您正在使用它来将模型映射到现有数据库。然后,您可以尝试执行以下操作:

Since modelBuilder.Entity<BaseModel>() will use TPH inheritance approach, I assume you are not using EF code first approach for database creation and you are using it to map your models to an existing database. Then you can try something like this:

型号:

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

public class BaseModel
{
    public BaseModel(int modelType)
    {
        ModelType = modelType;
    }
    public int Id { get; set; }
    public int ModelType { get; set; }

    public ICollection<Translation> Translations { get; set; }// only for internal use
    public IEnumerable<Translation> ModelTypeTranslations
    {
        get
        {
            return this.Translations.Where(t => t.Model == this.ModelType);
        }
    }

}

public class SomeModel : BaseModel
{
    public SomeModel() : base(1) { }
    public int SomeProperty { get; set; }
}

public class AnotherModel : BaseModel
{
    public AnotherModel() : base(2) { }
    public int AnotherProperty { get; set; }
}

DbContext:

public class MyDbContext: DbContext
{
    ...

    public DbSet<Translation> Translations { get; set; }
    public DbSet<SomeModel> SomeModels { get; set; }
    public DbSet<AnotherModel> AnotherModels { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
        modelBuilder.Entity<Translation>().HasKey(e => e.Id);

        var baseModelTypes = typeof(BaseModel).Assembly.GetExportedTypes()
            .Where(t => typeof(BaseModel).IsAssignableFrom(t) && t != typeof(BaseModel)).ToList();

        foreach (var type in baseModelTypes)
        {
            modelBuilder.Entity<Translation>().HasOne(type).WithMany(nameof(BaseModel.Translations)).HasForeignKey(nameof(Translation.ModelId));

            modelBuilder.Entity(type).Ignore(nameof(BaseModel.ModelType));
            modelBuilder.Entity(type).Ignore(nameof(BaseModel.ModelTypeTranslations));
            modelBuilder.Entity(type).HasKey(nameof(BaseModel.Id));
        }
    }
}

您可以看到使用 ModelTypeTranslations 只能获取当前模型类型的Translations。

As you can see you can use ModelTypeTranslations to get Translations only for current model type.

我应该注意,这种方法可能会出现性能问题,因为它会按 ModelType 翻译 / code>仅在内存中。另外,我还尝试通过使用,但是我得到了,即使我只是安装了该软件包而没有调用 optionsBuilder.UseLazyLoadingProxies()。我希望它将在以后的版本中修复。

I should note this approach may have performance issues since it filters Translations by ModelType only in memory. Also I tried to avoid filtering in memory by using lazy loading but I got some exception even if I just installed that package without invoking optionsBuilder.UseLazyLoadingProxies(). I hope it will be fixed in the next releases.

这篇关于在Entity Framework Core中使用两列的一对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 02:58