加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

entity-framework – ViewModels和MVC中Entity Framework的一对

发布时间:2020-12-16 09:59:43 所属栏目:asp.Net 来源:网络整理
导读:我有一个应用程序,用于在数据库中存储有关顾问的信息.该模型是实体框架模型,数据库表是顾问,与许多其他表(WorkExperiences,Programs,CompetenceAreas等)具有一对多的关系.现在,当我想在View中创建一个新的Consultant对象时,我真的只想将一个Consultant对象作
我有一个应用程序,用于在数据库中存储有关顾问的信息.该模型是实体框架模型,数据库表是顾问,与许多其他表(WorkExperiences,Programs,CompetenceAreas等)具有一对多的关系.现在,当我想在View中创建一个新的Consultant对象时,我真的只想将一个Consultant对象作为模型传递给View.但是对于其中一个,有人建议我( Collection of complex child objects in Asp.Net MVC 3 application?)我不应该这样做,而是使用ViewModels.其次,也许这就是原因,当我尝试发布Consultant对象(如果在View中使用它作为模型)时,我得到一个错误,说“EntityCollection已经初始化”,并且错误的原因似乎是WorkExperiences等对象的集合.

所以我的第一个问题是为什么我收到这个错误.

但更重要的是,如果我应该使用ViewModel,我该如何正确地做到这一点?因为我事实上已经尝试了一些东西,并让它发挥作用.但是……代码很糟糕.任何人都可以告诉我我应该做什么,而不是让这个工作更干净?

让我告诉你我拥有什么(它再次起作用,但是代码是一场噩梦):

GET Create方法:

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

        return View(vm);
    }

Helper方法创建“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 Create方法:

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

Helper方法创建一个Consultant对象(这个特别糟糕,我必须检查集合是否为null,以防用户决定不在这些列表中添加任何东西……):

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已经初始化”错误“……).那么我应该怎么做呢?

解决方法

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

>您不希望暴露敏感数据,例如“Id”或“密码”.想象一下,您的顾问有一个Id和一个邪恶的用户打开编辑顾问页面并回发一个不同的Id.结果,邪恶的用户将成功更新不同的顾问.
>目前,您在视图中显示的内容与您的Consultant对象的外观相对应.但是如果你想添加不属于Consultant对象的额外信息(就像复选框字段一样简单).在这种情况下,您必须重写相当多的代码,创建ViewModel,映射它等.如果您从一开始就遵循ViewModel模式,您可以随时进行这种简单的更改.

关于您的代码 – 您可以尝试将AutoMapper与Nested Mappings一起用于此类转换.即使不这样做,使用投影也可以使代码更清晰.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读