正确地将viewmodel映射到实体

时间:2017-12-27 14:42:26

标签: c# asp.net-mvc entity-framework

我的实体为:

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映射到我的实体

3 个答案:

答案 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();
}