簡體   English   中英

實體框架核心中使用兩列的一對多關系

[英]one-to-many relation using two columns in Entity Framework Core

在我的項目中,我有一個表格Translation ,可以翻譯任何模型。 為實現此目的,該表有兩個字段: ModelModelId Model屬性包含一個表示模型類型的整數, ModelId具有此模型的id。
因此,例如: Product表的modeltype為id 1 要獲取ID為317的產品的所有翻譯,我搜索Model=1 AND ModelId=317

現在我想在Entity Framework Core中創建這種關系。 我的所有模型都繼承自BaseModel類, BaseModel具有一個屬性ModelType ,其中包含模型類型的id。 此字段未映射,因此在數據庫中不可用。

我試圖使用流暢的api創建關系,但它不允許我指定更多的列來過濾。

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

有沒有辦法創建這種關系,而無需為每個需要翻譯的查詢手動創建連接?

由於modelBuilder.Entity<BaseModel>()將使用TPH繼承方法,我假設您沒有使用EF代碼第一種方法來創建數據庫,而是使用它來將模型映射到現有數據庫。 然后你可以嘗試這樣的事情:

楷模:

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。

我應該注意這種方法可能存在性能問題,因為它只在內存中按ModelType過濾Translations 此外,我試圖通過使用lazy loading避免在內存中進行過濾,但即使我剛剛安裝了該包而沒有調用optionsBuilder.UseLazyLoadingProxies() ,我也遇到了一些異常 我希望它將在下一個版本中修復。

就在這里。 用這個:

modelBuilder.Entity<BaseModel>()
.HasMany(bm => bm.Translations)
.WithForeignKey(x => new { x.Key1, x.Key2 });

Key1和Key2顯然需要是關系的關鍵,你可能還需要為翻譯實體定義它們(按相同的順序)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM