Lio*_*ion 14 c# asp.net inheritance entity-framework entity-framework-mapping
我有一个我的内容模型:
class BaseModel {
public virtual string Content{ get; set; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
要仅显示数据,上面的模型就可以了.但我想添加编辑内容的功能.所以我需要为成员内容添加一个属性- 但这只应该在autor按下编辑按钮时发生,而不是在内容的常规视图中.
所以我创建了第二个继承BaseModel的模型,以便我可以用我的属性覆盖成员:
class EditableBaseModel : BaseModel {
[UIHint("MyEditor"), AllowHtml]
public override string Content{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,但由于继承,EF会创建一个额外的列鉴别器.它包含类的类型作为字符串.在我的情况下,它始终是BaseModel,因为我总是将EditableBaseModel转换为BaseModel,然后将它保存到数据库,如下所示:
myBbContextInstance.BaseModels.Add(editableBaseModelInstance as EditableBaseModel);
Run Code Online (Sandbox Code Playgroud)
因此,鉴别器列是浪费空间,我想删除它.我发现这可以使用NotMapped属性来完成.但是当我尝试保存模型时,这将导致以下异常:
无法找到EntityType'EditableBaseModel'的映射和元数据信息.
似乎NotMapped属性将让EF知道存在从BaseModel继承的另一个类,但EF不会获得有关此类的任何信息.但那不是我想要的.我需要告诉EF:EditableBaseModel不应该关心它,因为它只适合我的视图,并且永远不会用于数据库.
我怎样才能做到这一点?我发现的唯一方法是手动将EditableBaseModel实例转换为BaseModel对象,如下所示:
public ActionResult Save(EditableBaseModel editableBaseModel) {
var baseModel = new BaseModel() {
Content = editableBaseModel.Content
// ...
};
myDbContextInstance.BaseModels.Add(baseModel);
}
Run Code Online (Sandbox Code Playgroud)
但这似乎不是一个很好的方法,因为我有多重属性.而且它也不是很灵活,因为当我向BaseModel添加内容时,我还必须在这里添加它 - 这可能会导致奇怪的错误.
将EF
概念与MVC
概念混合成一个Model
可能不适合两者.在这种情况下,创建新BaseModel
内容并将内容复制EditableBaseModel
到BaseModel
您的内容是正确的方法.您可以使用AutoMapper在两个模型之间映射数据.
class EditableBaseModel
{
[UIHint("MyEditor"), AllowHtml]
public string Content{ get; set; }
}
public ActionResult Save(EditableBaseModel editableBaseModel) {
var baseModel = new BaseModel();
Mapper.Map<EditableBaseModel, BaseModel>(editableBaseModel, baseModel);
myDbContextInstance.BaseModels.Add(baseModel);
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
BaseModel
您是否考虑过使用按以下方式工作的构造函数:
public BaseModel(EditableBaseModel editableBaseModel) {
this.Content = editableBaseModel.Content
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
myBbContextInstance.BaseModels.Add(new BaseModel(editableBaseModelInstance));
Run Code Online (Sandbox Code Playgroud)