APS.NET MVC + EF (06)---模型

在實際開發中,模型每每被劃分爲視圖模型和業務模型兩部分,視圖模型靠近視圖,業務模型靠近業務,可是在具體編碼上,它們之間並非隔離的。mvc

   

6.1 視圖模型和業務模型

模型大多數時候都是用來傳遞數據的。然而即便在傳遞數據這一點上,也能夠看出,視圖須要的模型更加靈活一點,由於視圖變化性更大,而處理業務的模型更加穩定一些。所以,在實際開發中,每每有視圖模型和業務模型的區分。在實際開發中,爲了體現邏輯的分離,每每是視圖模型和業務模型分別定義。app

例如,在傳統三層開發中,咱們定義的實體類,能夠看做是業務模型的定義,在開發視圖時,可能會開發各類和User相關的視圖,如用戶註冊視圖、用戶狀態列表視圖、登陸視圖,這時候每每根據視圖構造不一樣的模型,由於它們依賴的數據都不太同樣,這些模型可稱爲視圖模型。 框架

這種方式的好處就是可讓業務模型比較穩定,不會由於視圖的變動而頻繁地去修改業務模型。可是從另外一方面來看,這種分離的方式也會有壞處。壞處之一就是帶來不少重複的代碼。另外一個壞處就是在動做方法中,模型自動綁定完視圖模型後,還須要再手動編碼把視圖模型映射到業務模型,帶來額外的工做量。 asp.net

在小型項目開發中,爲了簡化代碼,並不會徹底區分視圖模型和業務模型,但不意味着實際開發都這樣作。 工具

   

6.2 AutoMapper框架

AutoMapper 是一個可以實現由一個對象到另外一個對象間映射的輕量級框架,利用AutoMapper框架可讓咱們從視圖模型到業務模型轉換的繁瑣工做中解放出來。編碼

AutoMapper 框架是基於約定的。 spa

   

6.2.1 AutoMapper 框架的安裝

新建asp.net mvc 項目 AutoMapperExample,點擊 工具→NuGetB包管理器→管理解決方案的NuGet程序包,在彈出的界面中,搜索autoMapper,在搜索出的程序包而後安裝。.net

   

6.2.2 AutoMapper 框架的使用

咱們以常見的用戶角色案例來說解AutoMapper 的使用。對象

首先咱們建立角色和用戶兩個類。代碼以下。其中User類中的Role屬性是對Role類的引用。 開發

//角色

public class Role

{

public int Id { get; set; }

public string Name { get; set; }

}

//用戶

public class User

{

public int Id { get; set; }

public string LoginName { get; set; }

public string LoginPwd { get; set; }

public string Phone { get; set; }

public int RoleId { get; set; }

public Role Role { get; set; }

}

在建立註冊用戶時所需的視圖模型。代碼以下。

//註冊視圖中使用的視圖模型

public class RegUserVM

{

public int Id { get; set; }

public string LoginName { get; set; }

public string LoginPwd { get; set; }

public string ConfirmPwd { get; set; }

public string Phone { get; set; }

public int RoleId { get; set; }

}

在視圖模型中增長了ConfirmPwd屬性,並將Role屬性去除。

   

接下來咱們在程序中新建AutoMapper文件夾,用於存放對象映射的類,該文件夾下新建類AutoMapperConfig,該類處理全部的對象映射,即從一個對象轉化到另外一個對象。如示例1所示。

示例1

using AutoMapper; //引用命名空間

public class AutoMapperConfig

{

public static void Config()

{

Mapper.Initialize(cfg =>

cfg.CreateMap<RegUserVM, User>());

}

}

Mapper.Initialize()方法執行AutoMapper的初始化操做,此操做在一個應用程序中只能執行一次.在初始化方法中能夠初始化映射中的任何操做。

CreateMap()泛型方法,用來建立兩個類型的映射,第一個類型爲原類型,第二個類型爲目標類型。在這裏配置爲將視圖模型映射爲業務模型。

   

而後,在項目的Global.asax文件的Application_Start()方法中調用該靜態方法。代碼以下所示。

protected void Application_Start()

{

//調用AutoMapper配置

AutoMapper.AutoMapperConfig.Config();

   

AreaRegistration.RegisterAllAreas();

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

RouteConfig.RegisterRoutes(RouteTable.Routes);

BundleConfig.RegisterBundles(BundleTable.Bundles);

}

至此,全部AutoMapper的配置所有配置完成。

下面咱們完成用戶註冊功能。在控制器中建立兩個Action。如示例2所示。

示例2

[HttpGet]

public ActionResult Register()

{

return View();

}

[HttpPost]

public ActionResult Register(RegUserVM userVM)

{

//將視圖模型對象映射爲業務模型對象

User user = Mapper.Map<User>(userVM);

if (UserManager.Add(user))

{

return RedirectToAction("Login");

}

return View();

}

Mapper.Map<S,T> 執行映射方法 S爲源類型,T爲目標類型,參數爲源類型。

   

示例2中,AutoMapper 根據字段名稱去自動對應,並忽略大小寫。咱們應用 AutoMapper 省去了繁瑣的賦值操做。

   

6.2.3 映射規則

  • 默認規則
    • 默認狀況下,咱們的"原類型"和"目標類型"是根據屬性名稱進行匹配映射的。
    • 若是在目標類型的屬性與源類型中配有對應的屬性,則映射失敗(爲空)。
    • 在映射過程當中,會執行自動類型轉換。(6.2.0以上版本)
  • 反向映射

    在AutoMapper中 ReverseMap() 方法能夠配置爲反向映射。如示例3所示。

示例3

public class AutoMapperConfig

{

public static void Config()

{

Mapper.Initialize(cfg =>

cfg.CreateMap<RegUserVM, User>().ReverseMap());

}

}

   

  1. 指定映射字段

在實際的業務環境中,咱們的源類型和目標類型的字段不可能一對一的匹配,這個時候咱們就須要來指定他們的實際映射關係。如示例3所示。

示例3

//源類型

public class User

{

public int Id { get; set; }

public string LoginName { get; set; }

public string LoginPwd { get; set; }

public string Phone { get; set; }

public int RoleId { get; set; }

public Role Role { get; set; }

}

//源目標類型

public class UserVM

{

public int UserId { get; set; }

public string UserName { get; set; }

public string RoleName { get; set; }

}

   

public static void Config()

{

Mapper.Initialize(cfg => {

cfg.CreateMap<RegUserVM, User>().ReverseMap();

cfg.CreateMap<User, ListUserVM>().ReverseMap();

   

cfg.CreateMap<User, UserVM>()

.ForMember(vm => vm.UserId, opt => opt.MapFrom(s => s.Id)) //指定映射

.ForMember(vm=>vm.UserName,opt=>opt.MapFrom(s=>s.LoginName))

.ReverseMap());

});

}

  

ForMember()方法用來配置匹配信息。參數1:目標類型屬性的表達式,參數2:執行操做的選擇。

  1. 空值替換

    AutoMapper中容許設置一個備用值來代替源類型中的空值。如示例4所示。

示例4

public static void Config()

{

Mapper.Initialize(cfg => {

cfg.CreateMap<RegUserVM, User>().ReverseMap();

cfg.CreateMap<User, ListUserVM>().ReverseMap();

   

cfg.CreateMap<User, UserVM>()

.ForMember(vm => vm.UserId, opt => opt.MapFrom(s => s.Id))

.ForMember(vm=>vm.UserName,opt=>opt.MapFrom(s=>s.LoginName))

.ForMember(vm => vm.RoleName, opt => opt.NullSubstitute("普通用戶")).ReverseMap());

});

}

   

  1. 扁平化映射

    在AutoMapper中, 若是對目標類型上的任何屬性,方法或以"Get"爲前綴的方法不存在源類型上,則AutoMapper會將目標成員名稱拆分爲單個單詞。

    例如,在顯示用戶信息時,咱們只想顯示用戶的登陸名、電話和角色名稱三個屬性,代碼如示例5所示。

    示例5

// 顯示用戶信息的視圖模型

public class ListUserVM

{

public int Id { get; set; }

public string LoginName { get; set; }

public string Phone { get; set; }

public string RoleName { get; set; }

}

// AutoMapper配置

public static void Config()

{

Mapper.Initialize(cfg => {

cfg.CreateMap<RegUserVM, User>().ReverseMap();

cfg.CreateMap<User, ListUserVM>().ReverseMap();

});

}

// 控制器方法

public ActionResult Index()

{

Role role = new Role() { Id = 1, Name = "管理員" };

User user = new User() {

Id = 1, LoginName = "admin",

Phone = "111", Role=role

};

ListUserVM userVM = Mapper.Map<ListUserVM>(user);

return View(userVM);

}

程序運行後,userVM 對象的 RoleName 屬性會被賦值爲"管理員"。(RoleName屬性會和User類的 Role.Name 屬性進行匹配)

相關文章
相關標籤/搜索