的ViewModels和一个一对多的实体框架中MVC的关系? [英] ViewModels and one-to-many relationships with Entity Framework in MVC?

查看:145
本文介绍了的ViewModels和一个一对多的实体框架中MVC的关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有用于存储在数据库中的信息顾问的应用程序。该模型是一个实体框架模型和数据库表的顾问,一到许多关系到许多其他表(WorkExperiences,程序,CompetenceAreas等)。现在,当我想创建一个视图中创建新的对象顾问,我真的只是想传递一个咨询对象作为模型来查看。但对于一个,它已经建议箱(<一href=\"http://stackoverflow.com/questions/5060817/collection-of-complex-child-objects-in-asp-net-mvc-3-application\">Collection在Asp.Net MVC 3应用程序复杂的子对象?),我不应该这样做,而是使用的ViewModels来代替。其次,也许这就是原因,我得到一个错误说的EntityCollection已经初始化当我尝试,如果用它作为视图模型来邮咨询对象,而错误的原因似乎是对象的集合,如WorkExperiences。

I have an application for storing information about consultants in a database. The model is an Entity Framework model, and the database tables are Consultant with one-to-many relationships to a number of other tables (WorkExperiences, Programs, CompetenceAreas, etc). Now, when I want to create a new Consultant object in a View, I would really just want to pass a Consultant object as the model to the View. But for one, it has been suggested to me (Collection of complex child objects in Asp.Net MVC 3 application?) that I shouldn't do this, but use ViewModels instead. Secondly, and maybe this is the reason, I get an error saying "The EntityCollection has already been initialized" when I try to post the Consultant object if using it as a model in the View, and the cause of the error seems to be the collections of objects such as WorkExperiences.

所以我的第一个问题是,为什么我得到这个错误。

So my first question is why I'm getting this error.

但更重要的是,如果我应该使用一个ViewModel,我将如何做到这正常吗?因为我其实已经尝试过的东西,并得到它的工作。但是......在code是可怕的。谁能告诉我,我应该做的,而不是更清洁得到这个工作?

But more importantly, if I should instead use a ViewModel, how would I do that properly? Because I have in fact tried something, and got it working. But...the code is awful. Can anyone please tell me what I should be doing instead to get this working more cleanly?

让我告诉你,我有什么(即再次工作,但它是一个噩梦codewise):

Let me show you what I have (that again works, but is a nightmare codewise):

获取创建方法:

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

        return View(vm);
    }

Helper方法来创建视图模型(如果这实际上是在什么视图模型应该是类似):

Helper method to create the "ViewModel" (if this is in fact what a ViewModel is supposed to be like):

    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方法:

The POST Create method:

    [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方法来创建一个顾问对象(这是特别可怕的,在那里我有检查的集合不为空,如果用户决定不以这些列表添加任何东西...):

Helper method to create a Consultant object (this one is particularly awful, where I have to check that collections are not null, in case the user decides not to add anything in those lists...):

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

所以,再次它的工作原理,但远不及干净,如果我能有一个直接咨询对象使用(如果不是那个EntityCollection已初始化错误...),所以我应该怎么办它,而不是?

So, again it works, but is nowhere near as clean as if I could have used a Consultant object directly (if not for that "EntityCollection is already initialized" error"...). So how should I do it instead?

推荐答案

首先,你不应该用你的实体对象的视图模型,因为(和现在我能想到的至少有两方面的原因,但更多的是):

First of all, you shouldn't use your entity object as the viewmodel because (and I can think of at least two reasons right now, but there are more):


  1. 您不想暴露敏感数据,如ID或密码。想象一下,你的顾问有一个编号和邪恶的用户打开的编辑顾问页面,并会回不同的编号。其结果是,邪恶的用户将在不同的更新顾问成功。

  1. You don't want to expose sensitive data, such as 'Id' or 'Password'. Imagine your consultant has an Id and an evil user opens the edit consultant page and posts back a different Id. As a result, the evil user will succeed in updating different Consultant.

目前无论你显示视图对应于你的顾问对象是什么样子。但如果你想添加额外的信息,是不是在顾问对象(如一个复选框字段一样简单)的一部分。在这种情况下,你必须重写颇有几分code的,创建视图模型,图吧等。而如果按照从一开始的视图模型的模式,你可以做这个简单的变化,当您需要它。

Currently whatever you show in the View corresponds to what your Consultant object looks like. But in case you want to add extra info that is not part of the Consultant object (as simple as a checkbox field). In that case, you have to rewrite quite a bit of code, create the ViewModel, map it, etc. While if you follow the ViewModel pattern from the start, you can just make this simple change whenever you need it.

关于你提到的code - 你可以尝试使用 AutoMapper 嵌套映射这种类型的转换。即使你不这样做,你的code可以通过预测进行了一下清洁。

Regarding your code - you can try to use AutoMapper with Nested Mappings for this type of conversion. Even if you don't, your code can be made a bit cleaner by using projections.

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

这篇关于的ViewModels和一个一对多的实体框架中MVC的关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆