我有我的观点模型:
namespace projInterview.Models
{
public class QuestionViewModel
{
public piQuestion Question { get; set; }
public List<piAnswer> Answers { get; set; }
public piQuestionFavorite QuestionFavorite { get; set; }
public piQuestionLevel QuestionLevel { get; set; }
public QuestionViewModel(piQuestion question, List<piAnswer> answers )
{
Question = question;
Answers = answers;
}
}
}
VM是一个独立的类。我没有把它装到控制器上。
在我的控制器中:
namespace projInterview.Controllers {
public class QuestionController : Controller
{
private ProjectContext db = new ProjectContext();
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
piQuestion piquestion = db.piQuestions.Single(x => x.QuestionID == id);
List<piAnswer> piAnswers = db.piAnswers.Where((x => x.QuestionID == id)).ToList();
var questionViewModel = new QuestionViewModel(piquestion,piAnswers);
return View(questionViewModel);
}
}
当我到达这一行时:
piQuestion piquestion = db.piQuestions.Single(x => x.QuestionID == id);
我收到以下错误:
在模型生成期间检测到一个或多个验证错误:
projInterview.DAL.QuestionViewModel :: EntityType'QuesuesViewModel' 没有定义键。定义此EntityType的键。 questionViewModels:EntityType:EntitySet'searchViewModels'是 基于没有定义键的类型'QuestionViewModel'。
piQuestion
和piAnswer
都具有viewmodel正在使用的原始模型中的键。我做错了什么?
答案 0 :(得分:24)
等待等待 等待。视图模型与Entity框架上下文完全无关。它不应该与它相关联。你现在看来的是db.piQuestions
是IQueryable<QuestionViewModel>
,这是绝对错误的事情。视图模型对EF没有任何了解,EF对视图模型一无所知。
永远不要将您的视图模型映射到任何数据库或EF的东西。您为DBContext添加IQueryable<T>
属性的是域模型。这些是绑定到数据库表的模型。
然后在您的控制器操作中,您对数据库(DbContext)进行一次或多次调用,以便检索这些域模型中的一个或多个。然后,将这些域模型映射(复制属性)到单个视图模型。最后,将视图模型传递给视图。
另外作为旁注,视图模型通常具有默认构造函数。您不需要那些采用参数的特定构造函数。如果您尝试将此类视图模型作为控制器操作的参数,那么这将使默认模型绑定器变得疯狂。
总结一下:视图模型没有任何键。他们甚至不知道钥匙是什么。密钥是您的数据访问层特有的内容,也就是您的域模型。
答案 1 :(得分:14)
为了完成:在View scaffolder中选择模型时,需要一个域模型,因此它还预先填充了Data上下文类,因此它需要一个键。选择视图模型时,只需删除预填充的DAL类,并将DAL字段留空。
如果你实际上为viewmodel定义了一个键,正如我错误地做的那样,脚手架将viewmodel的定义添加到上下文类中。为了弥补我所做的混乱,我从上下文类中删除了viewmodel定义,并从我的viewmodels中删除了键。