我想更新数据库表。控制器接收具有适当数据的视图模型。如果我像下面的例子中那样分配每个成员变量,它就可以工作
[HttpPost]
public ActionResult Edit(Admin_vm vm) {
var result = (from Users in db.Users
where Users.ID == usrID
select Users
).FirstOrDefault();
result.CompanyName = vm.ModifyUser.CompanyName;
//this is where I would assign every single member variable
db.SaveChanges();
return View(vm);
}
但是,我想知道是否有办法直接分配视图模型对象,如下所示:
result = vm.ModifyUser;
这不会给我一个错误,但它不会分配成员变量。有一个简单的方法吗?
谢谢!
答案 0 :(得分:2)
一种可能的解决方案是使用AutoMapper
,只要属性被命名并键入相同,它就会自动将属性从一个对象映射到另一个对象。因此,您可以根据类中的属性名称执行类似的操作(如果属性名称不同,也可以定义自定义映射):
//create the map, this is normally done in a config file but can be done in many different places
Mapper.Initialize(x =>
{
x.CreateMap<User, type of vm.ModifyUser goes here>().ReverseMap();
}
//map the vm to the user, this will update all fields on result to what is contained in vm.ModifyUser assuming properties are named and typed the same.
....db query to retrieve result...
result = Mapper.Map<User>(vm.ModifyUser);
context.SaveChanges()
您可以通过NuGet包管理器添加AutoMapper
。这是一种广泛使用的工具,有很好的文档记录。
答案 1 :(得分:1)
您无法直接将视图模型对象设置为数据库实体对象,因为它们是不同类的对象。
相反,您可以映射每个属性,这可以手动完成(就像您现在所做的那样),使用反射或使用现有的库(如ValueInjecter或AutoMapper)。
如果两个对象非常相似且具有相同的属性名称,我使用ValueInjecter因为它非常快速且易于使用,AutoMapper速度要慢得多,但允许更复杂的映射(我遇到了严重的性能问题)它,但选择最适合你的情况,即速度与灵活性)。
以下是如何使用ValueInjecter为您的问题中的示例执行此操作:
添加ValueInjecter NuGet:
Install-Package ValueInjecter -Version 3.1.1.5
在控制器类中包含命名空间:
using Omu.ValueInjecter;
然后在你的行动中:
[HttpPost]
public ActionResult Edit(Admin_vm vm) {
var result = (from Users in db.Users
where Users.ID == usrID
select Users
).FirstOrDefault();
result.InjectFrom(vm.ModifyUser);
context.SaveChanges();
return View(vm);
}
对于Create方法,您需要先创建对象:
User user = new User();
user.InjectFrom(vm.ModifyUser);
答案 2 :(得分:0)
听起来像模型绑定器没有像你期望的那样工作。您可能需要编写自定义模型绑定器。以下示例来自here。此示例继承自DefaultModelBinder
,然后使用反射 ONLY 覆盖 指定 type(下面示例中的HomePageModels,但是将是您的ViewModel或特定的ViewModel对象 - 即Admin_vm
或ModifyUser
)。对于其他一切,它通常会绑定,这可能是首选。
public class HomeCustomDataBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(HomePageModels))
{
HttpRequestBase request = controllerContext.HttpContext.Request;
string title = request.Form.Get("Title");
string day = request.Form.Get("Day");
string month = request.Form.Get("Month");
string year = request.Form.Get("Year");
return new HomePageModels
{
Title = title,
Date = day + "/" + month + "/" + year
};
//// call the default model binder this new binding context
//return base.BindModel(controllerContext, newBindingContext);
}
else
{
return base.BindModel(controllerContext, bindingContext);
}
}
}