2017-12-27 264 views
0

我有我的实体:正确映射视图模型到实体

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

我认为正确的方法是使用AutoMapper,如下所述,请参阅我的答案并让我知道您的反馈。 – Aria

回答

0

通过使用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:

这是使用模型 - 视图存储库(数据访问核心)不是好主意,所以这将是更好地保持你的public void UpdateUser(User u),不改变它,在外面,最好是通过userUpdateUser不是UserViewModel就像你之前做过的一样。

EDIT2:

在我回答的帖子的看法非不相关的SOC(在关注点分离),即使我的...

1 - 当我通过UserViewModel我已经触犯了SOC ....

2-在另一方,如果我直接在Peresentation层获得用户,我也违反了SOC。

我认为最好的办法是中间层代理....

介绍< ---->代理< ---->库。

1

你正在做的属性值的映射(视图模型 - > enity模型)UpdateUser方法。因此,使用视图模型类(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方法,您可以将视图模型对象传递给此方法。

这将修复您的编译时错误(,这是您在问题中的当前问题),但要注意您在哪些图层中使用了哪些类。如果您太担心在数据访问层中使用视图模型类,则可以在中间服务层中执行此操作。但是,您将获得该层中的实体模型并在那里进行更新。

请记住,对于该问题没有明确的答案。 使用您认为可读且与项目/团队保持一致的方法。很多时候,我倾向于使用术语“普通DTO类”而不是“查看模型”,所以我可以平静地将这些术语转移到另一层。我将它们放在一个单独的项目中(称为Common DTO),这将跨越其他项目。这意味着我将在Web/UI层和数据访问/服务层中添加对此Common DTO项目的引用,并根据需要使用这些参考。

+0

UpdateUser方法位于我的存储库类中,它是mu数据项目的一部分,UserViewModel是webproject的一部分。我不认为这是你提到的正确方法。 – aman

+0

是的。所以这是一个你必须让自己做出的呼叫。哪些课程直到哪一层(这个问题没有明确的答案)。我的答案是解决你当前的编译时错误。由你决定哪些类应该是哪一层。很多时候,我把类叫做Common DTOs而不是视图模型,这将允许我将它传递给深层。 – Shyju

+0

我倾向于将这些常见的DTO类移到单独的DTO项目中,并将它在Web和数据访问项目中引用。 – Shyju

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(); 
} 
+0

为什么'用户'应该在'Save'中检索,而它可以作为'UserViewModel'传递.. – Aria

+0

@Aria:UserViewModel类属于表示层。存储库不应该有任何用户视图的知识。关注点分离。 – JuanR

+0

是SOC说的,但是仓库不知道表示层,如果他使用Id而不是'UserViewModel',那么你的句子和代码会更接近。 – Aria