MVC实体框架映射器查看模型更新表

时间:2017-01-11 19:48:55

标签: asp.net-mvc entity-framework mapper

...再次

我正在使用EF5 App进行MVC。我有一个用户实体,EF绑定数据库中的Users表...看起来像这样。

ClientInfo

我有一个模型类,我在创建视图中使用它....

public partial class Users
{
    public long User_id { get; set; }
    [Required]
    [StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")]
    public string LastName { get; set; }
    [Required]
    [StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")]
    public string Name { get; set; }
    public int ProcessState_id { get; set; }
    public string Sex { get; set; }

    [Required,Range(1, int.MaxValue, ErrorMessage = "El País es Obligatorio")]
    public int Country_id { get; set; }

    [Required]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    public string Email { get; set; }
    public System.DateTime CreationDate { get; set; }
    public Nullable<System.DateTime> UpDateTime { get; set; }
    [RegularExpression(@"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
    [Required]
    [StringLength(9, MinimumLength = 3, ErrorMessage = "Password cannot be longer than 9 characters.")]
    public string Password { get; set; }
    public string Url { get; set; }
    public byte[] Picture { get; set; }
    public string CodArea { get; set; }
    public string PhoneNumber { get; set; }
    public virtual Countries Countries { get; set; }
    public virtual ProcessStates ProcessStates { get; set; }
    public virtual States States { get; set; }
    [NotMapped] // Does not effect with your database
    [RegularExpression(@"^.{5,}$", ErrorMessage = "Minimum 3 characters required")]
    [StringLength(9, MinimumLength = 3, ErrorMessage = "Confirm Password cannot be longer than 9 characters.")]
    [Compare("Password")]
    public virtual string ConfirmPassword { get; set; }
}

Controller中的“我的创建方法”获取public class UserViewModel { public Users user { get; set; } public IList<SelectListItem> AvailableCountries { get; set; } } 实例...

我的创建方法看起来像这样。

UserViewModel

到目前为止一切顺利。

对于我的编辑视图,我需要更少的User类属性,所以我有一个新类,其中包含我需要的属性。此类称为public async Task<ActionResult> Create(UserViewModel model, System.Web.HttpPostedFileBase image = null) { try { if (ModelState.IsValid) { model.user.ProcessState_id = Security.WAITING; model.user.Rol_id = Security.ROL_PUBLIC; model.user.CreationDate = DateTime.Now; model.user.IP = Request.UserHostAddress; model.user.Url = UserValidation.EncriptacionURL(model.user.Email); if (image != null) { // product.ImageMimeType = image.ContentType; model.user.Picture= new byte[image.ContentLength]; image.InputStream.Read(model.user.Picture, 0, image.ContentLength); } _db.Users.Add(model.user); _db.SaveChanges(); return RedirectToAction("Create"); } model.AvailableCountries = GetCountries(); return View(model); } catch (RetryLimitExceededException /* dex */) { } return View(model); }

UserEditView

我还为编辑视图创建了一个新模型,名为public class UserEditView { public long User_id { get; set; } [Required] [StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")] public string LastName { get; set; } [Required] [StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")] public string Name { get; set; } [Required, Range(1, int.MaxValue, ErrorMessage = "El País es Obligatorio")] public int Country_id { get; set; } [Required] [EmailAddress(ErrorMessage = "Invalid Email Address")] public string Email { get; set; } public Nullable<System.DateTime> UpDateTime { get; set; } public byte[] Picture { get; set; } public string CodArea { get; set; } public string PhoneNumber { get; set; } public virtual Countries Countries { get; set; } } ,看起来像这样。

UserEditViewModel

在我的编辑方法中,我使用public class UserEditViewModel { public UserEditView user { get; set; } public IList<SelectListItem> AvailableCountries { get; set; } } Mapper实体与User绑定

UserEditView

当我想更新用户表时出现问题。

Edit方法获取public ViewResult Edit(int User_id=3) { Users users = _db.Users .FirstOrDefault(p => p.User_id == User_id); var config = new MapperConfiguration(cfg => { cfg.CreateMap<Users, UserEditView>(); }); IMapper mapper = config.CreateMapper(); UserEditView userEditView = mapper.Map<Users, UserEditView>(users); var model = new UserEditViewModel { user = userEditView, AvailableCountries = GetCountries(), }; return View(model); } 个实例。

UserEditViewModel

public async Task<ActionResult> Edit(UserEditViewModel model, System.Web.HttpPostedFileBase image = null) { try { if (ModelState.IsValid) {} } } 的实例为UserEditViewModel,但我需要一个UserEditView的实例,以便EF更新用户表。

我需要再次映射吗? 我如何获得用户实例?

我添加以下类

Users

我添加了我的Global.asax

 public static class AutoMapperBootStrapper
    {
        public static void BootStrap()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Users, UserEditView>();
                cfg.CreateMap<UserEditView, Users>();
            });
            IMapper mapper = config.CreateMapper();

        }

然后在控制器中...我做

 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AutoMapperBootStrapper.BootStrap();
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

但是 public ViewResult Edit(int User_id=3) { Users users = _db.Users.FirstOrDefault(p => p.User_id == User_id); UserEditView userEditView = Mapper.Map<Users, UserEditView>(users); }有错误......它说没有实例化Mapper。

问题是因为我定义了多个Mapper。如果我只定义一个,它工作得很好......

1 个答案:

答案 0 :(得分:2)

  

我需要再次映射吗?我如何获得用户实例?

您可以使用id从数据库中获取User模型,然后从视图模型中映射您需要更新的属性:

[HttpPost]
public ActionResult Edit(UserEditViewModel model, HttpPostedFileBase image = null)
{
    if (!ModelState.IsValid)
    {
        // Validation failed => redisplay the Edit form so that the
        // user can correct the errors
        return View(model);
    }

    var user = _db.Users.FirstOrDefault(p => p.User_id == model.user.User_id);
    if (user == null)
    {
        // no user with the specified id has been found in the database =>
        // there's nothing to update
        return NotFound();
    }

    // This will map only the properties of the user object that
    // are part of the view model
    Mapper.Map<Users, UserEditView>(model.user, user);

    // at this stage you could manually update some properties that
    // have not been mapped such as the uploaded image

    // finally persist the changes to the database
    _db.SaveChanges();

    // redirect to some other action to show the updated users
    return RedirectToAction("users");
}

您在问题中显示的代码:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Users, UserEditView>();
});

IMapper mapper = config.CreateMapper();

这绝对是 NOT 您应该在控制器操作中执行的操作。 AutoMapper映射应该每个应用程序生命周期只配置一次,理想情况下应用程序启动时,即对于Global.asax中Application_Start的Web应用程序。在控制器操作中,您应该只使用已配置的映射。我强烈建议您浏览AutoMapper的文档,以便更好地了解如何使用此框架。

来自documentation

的引用
  

我在哪里配置AutoMapper?

     

如果您正在使用静态Mapper方法,则只应进行配置   每个AppDomain发生一次。这意味着最好的地方   配置代码在应用程序启动时,例如Global.asax   ASP.NET应用程序的文件。通常,配置   bootstrapper类在它自己的类中,而这个bootstrapper类是   从启动方法调用。 bootstrapper类应该调用   Mapper.Initialize配置类型映射。