我正在尝试对同一个表使用两个不同的实体。拥有两个实体的目的是限制其中一个实体的属性数量,因为在其中一个编辑表单中,应该只能更改一些属性。
因此,为了避免将不可编辑的属性隐藏起来以保留其值,我认为只有一部分属性的单独实体是个好主意。
所以我有一个具有所有属性的实体,另一个只有一些属性。问题是我得到了这个例外:
`实体类型'ApplicationMapping'和'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);
}
}
我如何实现我想要做的事情?有没有更好/更简单的方法呢?
谢谢!
答案 0 :(得分:4)
我建议将单个实体映射到表,但创建两个“视图”实体,它们只包含表单所需的那些属性。
这些视图实体可以包含将输入的数据映射回底层实体的方法。
答案 1 :(得分:3)
您正在寻找的是TPH(Table Per Hierarchy)。这是一种关系继承模式,其中一个类及其所有子类共享同一个表,并且由Entity Framework本身支持。实际上,如果你所做的只是让一个实体从另一个实体继承,那么Entity Framework默认会部署这个模式。你根本不需要做任何特别的事情。
但是,有一个条件:由于基类上的属性必须足以能够将行成功保存到数据库,因此所有子类属性必须是可选的 - 至少在数据库级别上。您始终可以通过前端用户界面强制实施一个或多个属性。
<强>更新强>
扩展我在下面的评论,如果你要做的就是从表中返回一个数据子集,那么你已经拥有了所需的所有工具。您不需要两个单独的实体,只需要一个实体(在本例中为您的ApplicationMappingFull
类),然后您可以使用LINQ仅返回所需的列。
db.ApplicationMappingFulls.Select(m => new ApplicationMappingViewModel
{
SomeProperty = m.SomeProperty,
OtherProperty = m.OtherProperty
});
在幕后,EF会发出一个只会选择SomeProperty
和OtherProperty
列的查询,因为这就是所需要的。您的视图模型根本不会连接到EF;它只是一个保存EF返回的数据的类。
答案 2 :(得分:1)
另一种选择是让一个类派生自另一个,并隐藏或以其他方式中断您不希望允许编辑的字段。
作为一个例子......
class Full {
public string ValueA {get;set;}
}
class Limited : Full {
public new string ValueA {get; private set;}
}
这无疑是最好的解决方案,但您可以使用另一种选择。
答案 3 :(得分:-1)
你的问题有答案。
The entity types 'ApplicationMapping' and 'ApplicationMappingFull' cannot share table 'ApplicationMapping'
将实体类型映射到表时,您正在定义表的架构。如你所说,你有一个具有所有属性的实体,一个只有一些属性。将实体映射到表时,需要映射表的所有列。
所以在一行中,“这是不可能的”。
为了解决您的问题,您可以做Paddy建议的事情。否则,您可以创建具有最小必需属性的基类,然后扩展该类并添加其余属性。将模型传递给视图时,传递基类对象。但是,您可以在从数据库中获取记录时使用扩展类对象。