【发布时间】:2014-01-26 19:52:49
【问题描述】:
我正在尝试找出一种好的(“最好”,如果可能的话)方法来构建一个解决方案,在该解决方案中,我可以在使用 EF6 将更改提交回数据库之前对控制器中的 MVC 模型进行一些工作。
所以这里是一个例子——我在我的一个控制器类中有这个代码:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Role role)
{
if (ModelState.IsValid)
{
db.Entry(role).State = EntityState.Modified;
//***********---> HERE IS WHERE I WOULD PLACE THE PRE-SAVECHANGES CALL
db.SaveChanges();
return RedirectToAction("Index");
}
return View(role);
}
如上所述,我想在 db.SaveChanges() 之前调用“pre-savechanges”函数。关键是我想为我的所有控制器执行此操作,并且我希望在所有控制器中调用此函数的方式相同,以便此预保存实现是一致的(换句话说,函数名称应该相同,并且应该将模型作为参数——我试图避免以任何方式将函数名称与模型名称联系起来)。例如,该函数可能被称为 PreSaveChanges,它需要访问即将被持久化的模型(角色,在这种情况下,如上面的代码所示)。
我知道有很多方法可以实现这一点,但我想到的一种方法是向每个模型添加一个函数——但我没有看到模型中的函数示例,而且我没有足够的经验来理解这种方法的后果(例如可测试性)。我还考虑过某种控制反转/依赖注入解决方案,因为这通常似乎是一种流行的选择。无论采用哪种方法,我都不想要求 pre-savechanges 功能需要实际存在。换句话说,一些控制器的模型需要在持久化之前进行预处理,而另一些则不需要。我仍然希望我的所有控制器都尝试调用 pre-savechanges 函数,但如果它尚未定义或不存在,那很好 - 然后应该执行 dbSaveChanges() 行。
所以,快速浏览一些选项:
-
我考虑过在实用程序类中创建一个静态函数,它将我的模型(在本例中为保修模型)作为参数——但是我不知道接收函数应该接受泛型类型还是对象“对象”类型的类型——两者都需要一些反射代码,以便我知道传递了什么模型。我可能会有一个大的“if”块来查看类型(如果是角色,则执行此操作;如果是用户,则执行此操作;等等)。我的控制器中的调用可能看起来像这样:
Utility.PreSaveChanges(warrantymodel);
如果您认为这是最好的方法,PreSaveChanges 应该有一个 object 类型的参数还是应该接受一个泛型类型?
-
我还认为我可以将预保存功能放在模型本身中。如上所述,我喜欢在模型中包含预保存功能代码的想法,但我只是不知道这是否是个好主意。该代码如下所示:
warrantymodel.PreSaveChanges();
如果您认为这是最好的方法,您能否确认在模型中包含函数是可以的?这会打破某种 MVC 原则吗?
我只触及了依赖注入的皮毛——所以我不知道这是否会有所帮助。如果可以的话,我很想看一个简短的例子(我已经阅读了足够多的关于 DI 的内容,无需太多解释就可以理解它)。
【问题讨论】:
-
您的问题源于您的数据对象、业务对象和 UI 对象都是同一事物。您需要使用视图模型。
-
是的,这只是 MVC 脚手架提供的控制器逻辑中的一个简单示例。我理解并同意应该涉及更多的模型。我感谢您的建设性批评,但这个问题的重点更多地与添加预保存逻辑的位置有关,模型架构除外。
标签: c# asp.net-mvc entity-framework controller