我有一个商家模型和一个 EditBusinessViewModel 。
在MVC 4中,我会使用类似这样的代码来编辑记录:
[HttpPost]
public ActionResult Edit(MainMenu mainmenu)
{
if (ModelState.IsValid)
{
db.MainMenus.Attach(mainmenu);
db.ObjectStateManager.ChangeObjectState(mainmenu, EntityState.Modified);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(mainmenu);
}
现在,MVC 5中自动生成的代码如下所示,我已将此Action修改为仅包含来自EditBusinessViewModel的字段,并将其命名为 Edit2 :
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Edit2([Bind(Include = "ID,BusinessName,BusinessDescription,BusinessAddress,BusinessPhoneOne,BusinessPhoneTwo,BusinessWeb,BusinessEmail,BusinessMelRef")] EditBusinessViewModel business)
{
if (ModelState.IsValid)
{
db.Entry(business).State = EntityState.Modified;
db.SaveChanges();
return Redirect("~/Home/Index/" + business.ID);
}
return View(business);
}
我获取部分正常工作,我的模型和查看正在返回:
return View(new EditBusinessViewModel(business));
但是当我回帖时,我在这一行上收到错误:
db.Entry(business).State = EntityState.Modified;
实体类型EditBusinessViewModel不是当前上下文的模型的一部分。它不是它的原因和ViewModel的原因,我猜?
我想知道的是我可以使用此代码还是我应该做的其他事情?
更新
我一直在考虑这个问题,而ViewModel只是一个 ViewModel 所以现在我有:
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Edit2([Bind(Include = "ID,BusinessDescription,BusinessAddress,BusinessPhoneOne,BusinessPhoneTwo,BusinessWeb,BusinessEmail,BusinessMelRef")] EditBusinessViewModel business)
{
if (ModelState.IsValid)
{
business.UserEmail = User.Identity.GetUserName();
Business newbus = db.Businesses.Find(business.ID);
{
newbus.BusinessDescription = business.BusinessDescription;
newbus.BusinessAddress = business.BusinessAddress;
};
db.Entry(newbus).State = EntityState.Modified;
db.SaveChanges();
return Redirect("~/Home/Index/" + business.ID);
}
return View(business);
}
这样我就可以从视图模型中的视图回发我需要的数据,通过匹配的ID找到数据库中的实体,并用EF脚手架代码更新它。
有更好的方法吗?
答案 0 :(得分:5)
好吧,您将无法使用当前的代码,因为我相信您在自己的问题中指出了这一点。您正在使用两种不同的类型,一种是从数据库表映射的,另一种是您专门用于视图但未映射的类型。您的实体模型,您没有说哪个版本的EF,但是使用MVC 5我认为它是6或6.1。
所以你有EF文本模板生成的实体POCO,你有ViewModel。即使属性相同,EF也不会采用您的ViewModel类型,因为它在edmx中没有映射定义,这就是它说它不在您已经识别的当前上下文中的原因。
虽然有一些不错的方法可以在这个系统中工作。如果你想使用单独的实体和ViewModel,我个人在我自己的大部分代码中都会这样做。你可以:
如果我错过了您要找的内容,请在评论中回复。此外,如果没有看到两个模型的类定义,为上述建议提供代码示例有点困难。如果您认为一个适合您的用例,我认为描述应该足够了吗?但是,如果您想要一些简单的代码示例,请使用这些类的代码更新您的答案,我可以提供一些。
答案 1 :(得分:2)
来自您发布的代码段:
return View(new EditBusinessViewModel(business));
此处,business
不是您的ViewModel ,而是您的ViewModel构造函数中使用的变量(可能是您的数据库实体)。我只能假设将其存储在ViewModel的某个属性中。
public ActionResult Edit2([Bind(Include = "...")] EditBusinessViewModel business)
此处,business
是您的ViewModel。它可以看到EditBusinessViewModel
类型。但在该方法中,您可以进行以下调用:
db.Entry(business).State = EntityState.Modified;
EditBusinessViewModel
不是EF已知的类型,因为它是您的viewmodel。您应该将实体传递给数据库。 ViewModel只应在您的MVC项目中使用。
我非常确定您EditBusinessViewModel
的某个属性是您需要的实体。您在EditBusinessViewModel
构造函数中传递了实体,这一点模糊地证实了这一点。
我不知道该财产的名称,因为您没有发布ViewModel的课程。假设它被称为MyEntity
,这应该可以解决问题:
db.Entry(business.MyEntity).State = EntityState.Modified;
但为了清楚起见,我建议重命名该参数,以防止在单独使用business
变量之间产生混淆。将其更改为businessVM
或类似内容,以便始终提醒您使用 ViewModel ,而非实体。