[英]one-to-many relation using two columns in Entity Framework Core
在我的項目中,我有一個表格Translation
,可以翻譯任何模型。 為實現此目的,該表有兩個字段: Model
和ModelId
。 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.