MVC Entity Framework 映射器以查看要更新的模型 table

MVC Entity Framework Mapper to View Model to Update table

再次...

我正在使用 EF5 应用程序制作 MVC。我有一个用户实体,EF 与数据库中的用户 table 绑定...看起来像这样。

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; }
}

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

public class UserViewModel
{
    public Users user { get; set; }
    public IList<SelectListItem> AvailableCountries { get; set; }
}

我在控制器中的创建方法获得了一个 UserViewModel 实例...

我的创建方法如下所示。

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);
}

到目前为止一切顺利。

对于我的编辑视图,我需要来自用户 class 的较少属性,所以我有一个新的 class,其中包含我需要的属性。这个class叫做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; }
}

在我的编辑方法中,我使用 MapperUser 实体与 UserEditView

绑定
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);
}

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

Edit 方法获取 UserEditViewModel 个实例。

public async Task<ActionResult> Edit(UserEditViewModel model, System.Web.HttpPostedFileBase image = null)
{
    try
    {
        if (ModelState.IsValid)
        {}
    }
}

UserEditViewModel 有一个 UserEditView 的实例,但我需要一个 Users 的实例,以便 EF 更新用户 Table.

我需要重新映射? 如何获取用户实例?

我添加以下内容Class

 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();

        }

然后我添加 Global.asax

 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.Map有一个错误...它说Mapper没有实例化。

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

I need to Map again? How can I get a Users Instance?

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

[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();

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

引自documentation

Where do I configure AutoMapper?

If you're using the static Mapper method, configuration should only happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications. Typically, the configuration bootstrapper class is in its own class, and this bootstrapper class is called from the startup method. The bootstrapper class should call Mapper.Initialize to configure the type maps.