C# ASP.NET EF从未映射类中删除鉴别器列
我有一个我的内容模型:C# ASP.NET EF从未映射类中删除鉴别器列,c#,asp.net,entity-framework,inheritance,entity-framework-mapping,C#,Asp.net,Entity Framework,Inheritance,Entity Framework Mapping,我有一个我的内容模型: class BaseModel { public virtual string Content{ get; set; } // ... } 要仅显示数据,可以使用上面的模型。但是我想添加编辑内容的功能。因此,我需要为成员内容添加一个属性——但这应该只在自动按下编辑按钮时发生,而不是在内容的常规视图中 因此,我创建了第二个模型,该模型继承自BaseModel,以便我可以使用我的属性覆盖该成员: class EditableBaseModel : BaseM
class BaseModel {
public virtual string Content{ get; set; }
// ...
}
要仅显示数据,可以使用上面的模型。但是我想添加编辑内容的功能。因此,我需要为成员内容添加一个属性——但这应该只在自动按下编辑按钮时发生,而不是在内容的常规视图中
因此,我创建了第二个模型,该模型继承自BaseModel,以便我可以使用我的属性覆盖该成员:
class EditableBaseModel : BaseModel {
[UIHint("MyEditor"), AllowHtml]
public override string Content{ get; set; }
}
这很好,但是由于继承EF创建了一个额外的列鉴别器。它以字符串形式包含类的类型。在我的例子中,它总是BaseModel,因为在保存到数据库之前,我总是将EditableBaseModel转换为BaseModel,如下所示:
myBbContextInstance.BaseModels.Add(editableBaseModelInstance as EditableBaseModel);
myBbContextInstance.BaseModels.Add(new BaseModel(editableBaseModelInstance));
因此,鉴别器列是对空间的浪费,我想删除它。我发现这是可以做到的。但当我尝试保存模型时,这将导致以下异常:
找不到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);
}
但这似乎不是一个好方法,因为我有多重属性。它也不是很灵活,因为当我向BaseModel添加一些东西时,我也必须在这里添加它-这可能会导致奇怪的错误 您是否考虑过在
BaseModel
中使用构造函数,其工作方式如下:
public BaseModel(EditableBaseModel editableBaseModel) {
this.Content = editableBaseModel.Content
}
然后像这样使用它:
myBbContextInstance.BaseModels.Add(editableBaseModelInstance as EditableBaseModel);
myBbContextInstance.BaseModels.Add(new BaseModel(editableBaseModelInstance));
将
EF
概念与MVC
概念混合到模型中可能不适合两者。在这种情况下,创建新的BaseModel
并像您那样将EditableBaseModel
的内容复制到BaseModel
是正确的方法。可以用于在两个模型之间映射数据
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);
.
.
.
}
类EditableBaseModel
{
[UIHint(“MyEdit”),AllowHtml]
公共字符串内容{get;set;}
}
公共操作结果保存(EditableBaseModel EditableBaseModel){
var baseModel=新的baseModel();
Mapper.Map(editableBaseModel,baseModel);
myDbContextInstance.BaseModels.Add(baseModel);
.
.
.
}
底线是,在实体框架中使用继承,您不能用两种不同的类型来表示数据库中的同一条记录
换句话说,如果以任何方式使用继承,EF可以将数据库中的任何行具体化为一种类型。所以,无论有没有鉴别器,你想要的永远都是不可能的
我认为与EditableBaseModel
之间的转换是一个可行的选择。或者将BaseModel
包装在EditableBaseModel
中,后者具有委托属性,如
public string Content
{
[UIHint("MyEditor"), AllowHtml]
get { return _baseModel.Content; }
set { _baseModel.Content = value; }
}
这是一种常见的模式,称为Decorator。请注意,在这种情况下(或转换时),您不应将EditableBaseModel
注册为EF模型中的实体
从技术上讲,另一种方法是可能的。您可以通过以下方式具体化任何对象。您可以将BaseModel
仅用于显示目的,并将EditableBaseModel
用作映射的实体类<代码>基本模型
s则可以通过
myBbContextInstance.Database.SqlQuery<BaseModel>("SELECT * FROM dbo.BaseModel");
myBbContextInstance.Database.SqlQuery(“从dbo.BaseModel中选择*);
当然,查询可以参数化以过滤模型。BaseModel
s将不会被上下文跟踪,但由于您只想显示它们,因此不需要这样做。这是我看到的用另一种类型表示(排序)数据库中一条记录的唯一方法
虽然我提到了技术上的可能性,但这并不意味着我推荐它。但是,即使对于“可编辑”选项,我也更喜欢使用视图模型。我不喜欢数据层和UI之间的这种紧密耦合。为什么不在BaseModel中添加一个非映射的布尔字段,这将表明用户希望更改内容?因为我使用UIHint属性插入部分视图,就像我的编辑器中的部分视图一样。似乎无法在运行时设置此属性。属性是按类设置的,而不是按实例设置的。在我看来,您可以在局部视图中使用一个条件,该条件基于一个标志字段,将显示或隐藏编辑控件属性到
EditableBaseModel
?是的,我尝试了一个类似的解决方案,在EditableBaseModel中放置了一个名为ToBaseModel的方法,该方法返回一个BaseModel实例。它可以工作,但我不喜欢这个解决方案,因为当我更改模型时,我还必须将属性添加到转换器方法中。所以我更喜欢像类型转换这样的自动化解决方案,但不幸的是这不起作用。我明白了。我在考虑构造函数,因为每当有人更改模型时,都会知道构造函数也必须更改,但是是的,自动化程度不高。。。