如何将多个实体映射到一个表中
本文关键字:一个 映射 实体 | 更新日期: 2023-09-27 18:30:07
我试图对同一个表使用两个不同的实体。拥有两个实体的目的是限制其中一个实体中的属性数量,因为在其中一个编辑表单上,应该只能更改少数属性。
因此,为了避免必须隐藏不可编辑的属性以保留它们的值,我认为只有一部分属性的单独实体是个好主意。
所以我有一个具有所有属性的实体,还有一个只具有一些属性的实体。问题是我得到了这个例外:
`实体类型"ApplicationMapping"answers"ApplicationMappingFull"无法共享表"ApplicationMapping",因为它们不在类型层次结构相同或没有有效的一对一外键它们之间具有匹配主键的关系。
实体配置类如下所示:
class ApplicationMappingFullConfiguration : EntityTypeConfiguration<ApplicationMappingFull>
{
public ApplicationMappingFullConfiguration()
{
ToTable("ApplicationMapping");
HasKey(p => p.Id);
}
}
class ApplicationMappingConfiguration : EntityTypeConfiguration<ApplicationMapping>
{
public ApplicationMappingConfiguration()
{
ToTable("ApplicationMapping");
HasKey(p => p.Id);
}
}
我如何才能实现我想要做的事情?有更好/更简单的方法吗?
谢谢!
我建议将单个实体映射到表,但创建两个仅包含表单所需属性的"视图"实体。
这些视图实体可以包含将输入的数据映射回基础实体的方法。
您想要的似乎是TPH(每层次表)。这是一种关系继承模式,其中一个类及其所有子类共享同一个表,并由实体框架本机支持。事实上,如果您所做的只是让一个实体从另一个实体继承,那么EntityFramework默认情况下会部署此模式。你根本不需要做任何特别的事情。
然而,有一个条件:由于基类上的属性本身必须足够,才能成功地将行保存到数据库中,因此所有子类属性都必须是可选的,至少在数据库级别上是可选的。您可以始终通过前端用户界面强制要求一个或多个属性。
更新
根据我下面的评论,如果你只想从表中返回一个子集数据,那么你已经拥有了所需的所有工具。您不需要两个单独的实体,只需要一个实体(在本例中为ApplicationMappingFull
类),然后您可以使用LINQ只返回您需要的列。
db.ApplicationMappingFulls.Select(m => new ApplicationMappingViewModel
{
SomeProperty = m.SomeProperty,
OtherProperty = m.OtherProperty
});
在幕后,EF将发出一个只选择SomeProperty
和OtherProperty
列的查询,因为这就是所需的全部内容。您的视图模型根本不会连接到EF;它只是一个用来保存EF返回的数据的类。
另一种选择是让一个类从另一个派生,并隐藏或以其他方式中性化您不希望编辑的字段。
举个例子。。。
class Full {
public string ValueA {get;set;}
}
class Limited : Full {
public new string ValueA {get; private set;}
}
无可否认,这不是最好的解决方案,但也是您可以使用的另一种选择。
你的问题有答案。
The entity types 'ApplicationMapping' and 'ApplicationMappingFull' cannot share table 'ApplicationMapping'
将实体类型映射到表时,就是在定义表的架构。正如您所说,您有一个具有所有属性的实体,还有一个仅具有某些属性的实体。将实体映射到表时,需要映射表的所有列。
所以在一句话中,"这是不可能的"。
要解决您的问题,您可以按照Paddy的建议进行操作。否则,您可以创建一个具有最少必需属性的基类,然后扩展该类并添加其余属性。将模型传递给视图时,传递基类对象。但是,您可以在从数据库获取记录时使用扩展类对象。