在Entity Framework Core中使用两列的一对多关系

在我的项目中,我有一个表格Translation ,可以翻译任何模型。 为实现此目的,该表有两个字段: ModelModelIdModel属性包含一个表示模型类型的整数, ModelId具有此模型的id。
因此,例如: Product表的modeltype为id 1 。 要获取ID为317的产品的所有翻译,我搜索Model=1 AND ModelId=317

现在我想在Entity Framework Core中创建这种关系。 我的所有模型都inheritance自BaseModel类, BaseModel具有一个属性ModelType ,其中包含模型类型的id。 此字段未映射,因此在数据库中不可用。

我试图使用流畅的api创建关系,但它不允许我指定更多的列来过滤。

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

有没有办法创建这种关系,而无需为每个需要翻译的查询手动创建连接?

由于modelBuilder.Entity()将使用TPHinheritance方法,我假设您没有使用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 Translations { get; set; }// only for internal use public IEnumerable 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 Translations { get; set; } public DbSet SomeModels { get; set; } public DbSet AnotherModels { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { ... modelBuilder.Entity().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().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() ,我也遇到了一些exception 。 我希望它将在下一个版本中修复。

就在这里。 用这个:

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

Key1和Key2显然需要成为关系的关键,您可能还需要为Translation实体定义它们(按相同的顺序)。