我的实体为:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
我的UserViewModel为
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
我在控制器中使用以下内容:
//This is called from my view via ajax
public void Save(UserViewModel uv)
{
// this throws error: cannot convert from UserViewModel to Entity.User
MyRepository.UpdateUser(uv);
}
我在存储库类中的UpdateUser如下:
public void UpdateUser(User u)
{
var user = GetUserDetails(u.Id);
user.Name = u.Name;
user.Address = u.Address;
//using entity framework to save
_context.SaveChanges();
}
如何正确地将我的控制器中的UserViewModel映射到我的实体
答案 0 :(得分:4)
使用AutoMapper可以执行以下操作:
public void Save(UserViewModel uv)
{
// this throws error: cannot convert from UserViewModel to Entity.User
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<UserViewModel , User>();
});
User u = config.CreateMapper().Map<User>(uv);
MyRepository.UpdateUser(u);
}
或手动:
public void Save(UserViewModel uv)
{
User u = new User()
{
Id = uv.Id
Name = uv.Name;
Address = uv.Address;
};
MyRepository.UpdateUser(u);
}
如果您更改视图模型和模型,手动执行此操作并不好,那么您也应该更改代码,但使用Automapper
您不需要更改代码。
<强> EDIT1:强>
在存储库(DataAccess Core)中使用模型视图不是一个好主意,所以最好保留public void UpdateUser(User u)
并且不要更改它,在外面最好通过{{ 1}}到user
而非UpdateUser
就像你之前所做的那样。
<强> EDIT2:强>
在我看来,没有回复的帖子与SOC(关注点分离)甚至是我的......
1-当我通过UserViewModel
时,我违反了SOC ......
2-另一方面,如果我直接在Peresentation层中使用User,我也违反了SOC。
我认为最好的方法是将中间层作为代理......
演示&lt; ----&gt;代理&lt; ----&gt;库中。
答案 1 :(得分:2)
您正在您的存储库UpdateUser
方法中执行属性值(view model-&gt; enity模型)的映射。因此,请使用视图模型类(UserViewModel
)作为参数类型。
public void UpdateUser(UserViewModel u)
{
// Get the entity first
var user = GetUserDetails(u.Id);
// Read the property values of view model object and assign to entity object
user.Name = u.Name;
user.Address = u.Address;
//using entity framework to save
_context.SaveChanges();
}
现在,通过Save
方法,您可以将视图模型对象传递给此方法。
这将修复您的编译时错误(这是您在问题中的当前问题),但要注意您在哪些层中使用的类。如果您过于担心在数据访问层中使用视图模型类,则可以在中间服务层中执行此操作。但是,您将在该层中获取实体模型并在那里进行更新。
请记住,该问题没有明确的答案。 使用您认为可读且与项目/团队一致的方法。通常,我倾向于使用术语&#34; Common DTO类&#34;而不是&#34;查看模型&#34;所以我可以和平地将那些传递到另一层。我将它们保存在一个单独的项目中(称为 Common DTO ),这将跨越其他项目。这意味着我将在我的Web / UI层和我的数据访问/服务层添加对此Common DTO项目的引用,并根据需要使用它们。
答案 2 :(得分:1)
您的存储库处理类型为User
的对象,因此您需要将值映射回该类型的实例,然后进行调用。
假设您有一种方法可以让用户名为GetUser
:
public void Save(UserViewModel uv)
{
var user = MyRepository.GetUser(uv.Id);
user.Name = uv.Name;
user.Address = uv.Address;
MyRepository.UpdateUser(user);
}
然后,您可以将更改保存在存储库类中。您可以附加对象以确保在对象是在不同的上下文中创建时没有问题:
public void UpdateUser(User u)
{
_context.Users.Attach(u);
_context.Entry(u).State = EntityState.Modified;
_context.SaveChanges();
}