在 Entity Framework Core 中使用两列的一对多关系 [英] one-to-many relation using two columns in Entity Framework Core
问题描述
在我的项目中,我有一个表 Translation
可以对任何模型进行翻译.为此,该表具有两个字段:Model
和 ModelId
.Model
属性包含一个表示模型类型的整数,ModelId
具有此模型的 id.
因此,例如:Product
表具有模型类型 id 1
.要获取 ID 为 317
的产品的所有翻译,我搜索带有 Model=1 AND 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.
我曾尝试使用 fluent 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
将使用 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; }
}
数据库上下文:
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
获取仅适用于当前模型类型的翻译.
As you can see you can use ModelTypeTranslations
to get Translations only for current model type.
我应该注意到这种方法可能存在性能问题,因为它仅在内存中按 ModelType
过滤 Translations
.我还尝试通过使用 lazy loading
来避免在内存中进行过滤 但我得到了 一些例外,即使我只是安装了那个包而不调用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 中使用两列的一对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!