2017-12-27 228 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