【问题标题】:How to create new entity object, modify it in Model before SaveChanges()如何创建新的实体对象,在 SaveChanges() 之前在 Model 中修改它
【发布时间】:2011-10-19 09:59:23
【问题描述】:

我已经在这个问题上纠结了好几个小时,但无法弄清楚问题所在。所以我将 ASP.NET MVC 3 与 Entity Framework 4.1 一起使用。我正在从头开始编写帐户管理控制器和模型。我的问题是,每当控制器从视图接收到填充的实体对象并将其发送到模型时,如果我尝试预先修改任何字段,模型将不会保存它。

这是我模型的相关部分,名为 ModelManager.cs:

public class MemberManager
{
    private DAL db = new DAL();

    public void Add(Member member)
    {
        member.Password = Crypto.HashPassword(member.Password);
        db.Members.Add(member);
        db.SaveChanges();
    }

该模型从控制器获取Member member实体对象作为参数,其相关部分如下:

    [HttpPost]
    public ActionResult Register(Member member)
    {
            try
            {
                if (ModelState.IsValid)
                {
                    MemberManager memberManager = new MemberManager();
                    if (!memberManager.UsernameExist(member.Username))
                    {
                        memberManager.Add(member);
                        FormsAuthentication.SetAuthCookie(member.FirstName, false);
                        return RedirectToAction("Welcome", "Home");
                    }
                    else
                    {
                        ModelState.AddModelError("", "Username already taken.");

                    }
                }
            }
            catch
            {
                ModelState.AddModelError("", "Could not complete account creation. Please try again.");
            }

            return View(member);
    }

如果我删除对模型中实体对象的任何属性的 任何 修改,代码将起作用(即,我删除了我 Crypto.HashPassword 实体对象的密码字段的行。起初我以为问题出在 HashPassword 上,但如果我将该行更改为简单地将 member.Password 更改为字符串“1”,它也不起作用。

那么,我做错了什么?我对编程完全陌生,所以如果问题非常明显,请耐心等待。是否可以在创建帐户时从视图创建实体对象,将其发送到控制器,然后将其传递给模型,模型会修改密码以在保存之前对其进行哈希处理?

顺便说一句,引发的异常错误是:

System.Data.Entity.Validation.DbEntityValidationException:一个或多个实体的验证失败。有关更多详细信息,请参阅“EntityValidationErrors”属性。在 System.Data.Entity.Internal.InternalContext.SaveChanges() 在 System.Data.Entity.Internal.LazyInternalContext.SaveChanges() 在 System.Data.Entity.DbContext.SaveChanges() 在 Politiq.Models.ObjectManager.MemberManager.Add (成员成员)在 C:\Users\C 中。 Yehia\Documents\Visual Studio 2010\Projects\Politiq2\Models\ObjectManager\MemberManager.cs:C:\Users\C 中 Politiq.Controllers.AccountController.Register(成员成员)的第 21 行。 Yehia\Documents\Visual Studio 2010\Projects\Politiq2\Controllers\AccountController.cs:39 行

【问题讨论】:

  • 我没有看到您实际上添加 Member 实例到数据库上下文。另外,如果您详细说明“不会保存”,那就太好了。
  • 您是否将成员添加到db 的任何位置? db.Add(member) 之类的东西?
  • 是的,很抱歉在这里复制它时我忘记重新添加db.Members.Add(member) 行(我之前在我的代码中有它,但为了测试问题的各种理论而删除它)。我现在重新添加了那行。
  • 关于“不保存”Dan,我收到错误消息“无法完成帐户创建...”,这是我在控制器的 catch 字段中定义的。该条目不会出现在我的数据库中。如果我删除密码修改行,它会通过并最终出现在我的数据库中。
  • 将您的catch 更改为catch (Exception exception) 并添加断点以查看实际的异常消息是什么。

标签: c# asp.net entity-framework asp.net-mvc-3


【解决方案1】:

我看到您的成员实例是由模型绑定器创建的(即不在您的代码中),但我没有看到它实际上被添加到表中。你错过了db.Members.Add() 电话吗?

无论如何,我建议为“注册数据”创建一个单独的模型类,这样您就不要让 MVC 模型绑定器创建Member 实例,而是自己创建它。原因是这种方法不安全,因为默认情况下,活页夹会尝试将每个 HTML 输入字段分配给匹配的属性,因此黑客可以在您的对象中注入 Id 值,这将导致异常(并且可能还有一些其他讨厌的东西)。

当然,您可以使用[Bind(Exclude="ID")],这样它就不会尝试填充 ID,但我仍然会将数据库实体和用户输入分开:

会员控制器

public ActionResult Register(RegistrationForm form)

会员管理器

public Member RegisterMember(RegistrationForm form)

【讨论】:

  • Dan,我按照您的建议制作了一个单独的 NewMemberModel 模型,然后在保存之前将该模型的字段映射到我在该方法中创建的成员实体对象的 MemberManager.Add() 方法。成功了,谢谢!
  • @cyehia:很高兴我帮助了你!还有一个different approach with interfaces,我觉得这很令人兴奋。它可能并不总是最合适的(例如,有时您的表单和数据库类可能有很大不同),但肯定值得一看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
相关资源
最近更新 更多