MVC 中的 ViewModel 和与实体框架的一对多关系?

2024-02-19

我有一个用于在数据库中存储有关顾问的信息的应用程序。该模型是一个实体框架模型,数据库表与许多其他表(工作经验、计划、能力区域等)具有一对多关系。现在,当我想在视图中创建一个新的 Consultant 对象时,我实际上只想将 Consultant 对象作为模型传递给视图。但首先,有人向我建议(Asp.Net MVC 3 应用程序中复杂子对象的集合? https://stackoverflow.com/questions/5060817/collection-of-complex-child-objects-in-asp-net-mvc-3-application)我不应该这样做,而是使用 ViewModels。其次,也许这就是原因,当我尝试发布顾问对象(如果将其用作视图中的模型)时,我收到一条错误消息“EntityCollection 已被初始化”,并且错误的原因似乎是对象的集合,例如 WorkExperiences。

所以我的第一个问题是为什么我会收到此错误。

但更重要的是,如果我应该使用 ViewModel,我该如何正确地做到这一点?因为我实际上已经尝试过一些东西,并且成功了。但是......代码很糟糕。谁能告诉我我应该做什么才能让这个工作更干净?

让我向您展示我所拥有的(这再次有效,但在代码方面是一场噩梦):

GET 创建方法:

    public ActionResult Create()
    {
        Consultant consultant = new Consultant();
        ConsultantViewModel vm = GetViewModel(consultant);

        return View(vm);
    }

创建“ViewModel”的辅助方法(如果这实际上是 ViewModel 应该的样子):

    private ConsultantViewModel GetViewModel(Consultant consultant)
    {
        ConsultantViewModel vm = new ConsultantViewModel();
        vm.FirstName = consultant.FirstName;
        vm.LastName = consultant.LastName;
        vm.UserName = consultant.UserName;
        vm.Description = consultant.Description;

        vm.Programs = consultant.Programs.ToList();
        vm.Languages = consultant.Languages.ToList();
        vm.Educations = consultant.Educations.ToList();
        vm.CompetenceAreas = consultant.CompetenceAreas.ToList();
        vm.WorkExperiences = consultant.WorkExperiences.ToList();
        return vm;
    }

POST 创建方法:

    [HttpPost]
    [ValidateInput(false)] //To allow HTML in description box
    public ActionResult Create(ConsultantViewModel vm, FormCollection collection)
    {
        try
        {
            Consultant consultant = CreateConsultant(vm);
            _repository.AddConsultant(consultant);
            _repository.Save();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

创建 Consultant 对象的帮助器方法(这个特别糟糕,我必须检查集合是否不为空,以防用户决定不在这些列表中添加任何内容......):

    private Consultant CreateConsultant(ConsultantViewModel vm)
    {
        Consultant consultant = new Consultant();
        consultant.Description = vm.Description;
        consultant.FirstName = vm.FirstName;
        consultant.LastName = vm.LastName;
        consultant.UserName = vm.UserName;

        if (vm.Programs != null)
            foreach (var program in vm.Programs)
                consultant.Programs.Add(program);
        if (vm.Languages != null)
            foreach (var language in vm.Languages)
                consultant.Languages.Add(language);
        if (vm.Educations != null)
            foreach (var education in vm.Educations)
                consultant.Educations.Add(education);
        if (vm.WorkExperiences != null)
            foreach (var workExperience in vm.WorkExperiences)
                consultant.WorkExperiences.Add(workExperience);
        if (vm.CompetenceAreas != null)
            foreach (var competenceArea in vm.CompetenceAreas)
                consultant.CompetenceAreas.Add(competenceArea);

        return consultant;
    }

所以,它再次工作,但远不像我可以直接使用 Consultant 对象那么干净(如果不是因为“EntityCollection 已初始化”错误”...)。那么我应该怎么做呢?


首先,您不应该使用实体对象作为视图模型,因为(我现在至少可以想到两个原因,但还有更多):

  1. 您不想暴露敏感数据,例如“ID”或“密码”。想象一下您的顾问有一个Id邪恶的用户打开编辑顾问页面并回发不同的内容Id。结果,邪恶的用户将成功更新不同的Consultant.

  2. 目前,您在视图中显示的任何内容都对应于您的Consultant对象看起来像。但如果您想添加不属于的额外信息Consultant对象(就像复选框字段一样简单)。在这种情况下,您必须重写大量代码、创建 ViewModel、映射它等。而如果您从一开始就遵循 ViewModel 模式,则可以在需要时进行简单的更改。

关于您的代码 - 您可以尝试使用AutoMapper with 对于这种类型的转换。即使您不这样做,也可以通过使用投影使您的代码变得更加简洁。

private ConsultantViewModel GetViewModel(Consultant consultant)
{
    return new ConsultantViewModel
               {
                   FirstName = consultant.FirstName,
                   LastName = consultant.LastName,
                   ...
                   vm.Programs = consultant.Programs.ToList(),
                   ...
               };
 }

 private Consultant CreateConsultant(ConsultantViewModel vm)
 {
     var consultant = new Consultant
                      {
                          Description = vm.Description,
                          FirstName = vm.FirstName,
                          ...
                       };

     if (vm.Programs != null)
     {
         vm.Programs.ForEach(consultant.Programs.Add);
     }
     ...

     return consultant;
}  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVC 中的 ViewModel 和与实体框架的一对多关系? 的相关文章

  • 实体类型处于“影子状态”意味着什么?

    在我的 ASP NET Core 1 0 MVC6 EF7 Web 应用程序中 我添加了一个迁移 该迁移添加了新的相关表 和相应的模型 我有以下模型快照 DbContext typeof ApplicationDbContext parti
  • ASP.Net MVC 3 JSON 模型绑定和服务器端模型验证与客户端验证混合

    我一直在使用新的 MVC3 Json 模型绑定 它非常好 目前 我可以将 JSON 发布到控制器并绑定它 模型验证也进展顺利 但如果模型无效怎么办 我想返回 JSON 并让客户端通知用户 就像在 mvc 中执行正常客户端验证的方式一样 有谁
  • 在实体框架 6 中使用 SqlQuery>

    我正在尝试在 EF 6 中执行 SQL 查询 select查询返回两个字符串列 例如select a b 并且可以有任意数量的行 我想将结果映射到字典 但我无法摆脱以下错误 错误 1 无法将类型 System Data Entity Inf
  • 防止更新 ASP.NET MVC 和实体框架中未更改的值

    我正在使用 ASP NET MVC 和实体框架 我有一个 编辑人员 网页 可以在其中编辑人员的字段 然后在回发操作中 我使用以下代码 var person objectCtx Persons Where s gt s Id id First
  • SimpleMemership CreateUserAndAccount 自定义

    我正在尝试添加一个新属性UserProfile我的模型中的类 public class UserProfile Key DatabaseGeneratedAttribute DatabaseGeneratedOption Identity
  • EntityHydrate 任务失败

    我最近安装了 Visual Studio 11 Beta 和 Visual Studio 2010 之后 我无法在 Visual Studio 2010 中构建依赖于 PostSharp 的项目 因此我卸载了 Visual Studio 1
  • .edmx 文件的用途是什么?

    edmx 文件的用途是什么 阅读 CSDL SSDL 和 MSL 规范 在我看来 edmx 文件仅在设计时使用 我们打算将它与其他 edmx 一起分发吗 看来我们需要分发 ssdl 和 或 csdl 文件 EDMX 是 Visual Stu
  • 使用 C++/CLI 包装非托管 C++ 类库 - 问题 2 - 集合

    Note 这篇文章代表了我的询问的问题 2 两个问题中都会重复介绍部分 达到数字之前的所有文本 因为它是回答问题可能需要的背景信息 问题简介 我有一个非托管 C 库 其中包含多个 更高级别 库所共有和共享的类和函数 我现在需要向 C Net
  • 具有不同 ID 字段名称的 EF Fluent API 多对多

    在这个问题中 Ef 多对多 https stackoverflow com questions 8927278 how to configure many to many relationship using entity framewor
  • MVC3 OutputCache VaryByHeader=未设置 Cookie

    我有以下操作方法 HttpGet Authorize OutputCache Duration 60 VaryByHeader Cookie Location OutputCacheLocation Any public ActionRes
  • ASP.NET MVC 4 Web Api 和 REST 经典服务之间的区别

    我看到了ASP Net MVC4 WebApi将服务公开为 Rest 服务 但实际上和正常有什么区别Rest and ASP Net MVC4 WebApi 我不确定你的意思normal Rest REST http en wikipedi
  • 用于派生对象列表的 MVC2 Modelbinder

    我想要一个与 Asp net MVC 2 中的默认 Modelbinder 一起使用的不同 派生 对象类型的列表 我有以下视图模型 public class ItemFormModel Required ErrorMessage Requi
  • .NET 5 EF Core SaveChangesAsync 因错误而挂起

    尽管这个问题有很多结果 但没有一个真正给我明确的答案 每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据 例如重复的主键 时 我都会看到以下日志 执行 DbCommand 失败 15 毫秒 我还在 SQ
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 在HTTP GET中使用MVC3的AntiForgeryToken来避免Javascript CSRF漏洞

    关于这个被黑客攻击的博客 http haacked com archive 2009 06 25 json hijacking aspx 我对实施提议的反 JSON GET 劫持解决方案犹豫不决 因为 缓解 JSON 劫持的推荐解决方案涉及
  • 实体框架映射枚举:指定的值不是类型“Edm.Int32”的实例参数名称:值

    我试图将实体框架查询的结果返回到我自己的 dto 类中 同时映射我的枚举 TradeType 我收到以下错误 指定的值不是类型 Edm Int32 的实例参数名称 值 知道如何修复或解决方法吗 Thanks public IEnumerab
  • 配置多个数据库Entity Framework 6

    在我的解决方案中 我有 2 个使用 Entity Framework 6 的项目 每个项目都指向不同的数据库 都使用相同的数据提供 SQL Server 我的解决方案中的第三个项目需要使用这两个数据库 我的问题是如何配置这些上下文 我尝试在
  • ASP.NET MVC 3 身份验证/授权 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我对 ASP NET MVC 3 以及一般的 MVC 非常陌生 在 ASP NET Web 窗体中 我使用主体和身份进行身份验证 这是在 MVC 中推
  • jQueryUI autoComplete 返回空列表

    在我的 asp net mvc3 应用程序中 我为搜索框添加了自动完成功能 当我测试它时 该操作返回了 3 个结果 您可以看到显示了一个列表 但是 这是一个空列表 您只看到 3 个 并且 li 标记之间没有任何内容 我很确定 操作没问题 因
  • 如何在 MVC5 中创建两种类型的用户?

    我正在创建 MVC5 应用程序 并且已经在使用 ASP NET Identity 来创建用户 因此 我已经有了 AspNetUsers 表 每当用户注册时 我都会在那里获得一个条目 我还有一个管理员角色 我可以手动指定哪个注册用户是管理员

随机推荐