" EntityCollection已经初始化"误差实体在Asp.Net MVC模式? [英] "EntityCollection already initialized" error with entity as model in Asp.Net MVC?

查看:265
本文介绍了" EntityCollection已经初始化"误差实体在Asp.Net MVC模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在与创建一个复杂的对象很大的困难。我有一个具有一对多关系的若干其他表的顾问表的EF模型。我想用顾问的对象作为模型,是因为这将是非常简单和容易(和它在的NerdDinner教程的做),因为我与没有其他物体一到多的关系做。问题是,这种关系导致此错误:EntityCollection已初始化当我试图张贴到创建方法

I'm having great difficulties with creating a complex object. I have an EF model with a Consultant table that has one-to-many relationships to a number of other tables. I wanted to use the Consultant object as the model as is because it would be very simple and easy (and as it's done in the NerdDinner tutorial), as I've done with other objects that didn't have one-to-many relationships. The problem is that these relationships cause this error: "EntityCollection already initialized" when I try to post to the Create method.

有几个人建议我使用一个ViewModel,而是和我发布了关于这个问题(<一个href=\"http://stackoverflow.com/questions/5083880/viewmodels-and-one-to-many-relationships-with-entity-framework-in-mvc\">ViewModels与实体框架的MVC?一到多的关系),因为我真的不明白。问题是code得到reeeeally可笑的......这是从我到目前为止AP $ P $ MVC中pciated简单相去甚远。

Several people have advised me to use a ViewModel instead, and I posted a question about this (ViewModels and one-to-many relationships with Entity Framework in MVC?) because I don't really understand it. The problem is the code gets reeeeally ridiculous... It's a far cry from the simplicity I've so far appreciated in MVC.

在这个问题我忘了提,除了创建方法,编辑方法使用相同的方法CreateConsultant(名字可能会产生误导,它实际上填充顾问对象)。所以,为了不具有附加的,说程序添加编辑时,我需要那个方法更加复杂。所以现在看起来是这样的:

In that question I forgot to mention that besides the Create method, the Edit method uses the same CreateConsultant method (the name may be misleading, it actually populates the Consultant object). And so in order not to have additional, say "Programs" added when editing, I needed to complicate that method further. So now it looks like this:

private Consultant CreateConsultant(ConsultantViewModel vm, Consultant consultant) //Parameter Consultant needed because an object may already exist from Edit method.
        {
            consultant.Description = vm.Description;
            consultant.FirstName = vm.FirstName;
            consultant.LastName = vm.LastName;
            consultant.UserName = User.Identity.Name;

            if (vm.Programs != null)
                for (int i = 0; i < vm.Programs.Count; i++)
                {
                    if (consultant.Programs.Count == i)
                        consultant.Programs.Add(vm.Programs[i]);
                    else
                        consultant.Programs.ToList()[i] = vm.Programs[i];
                }
            if (vm.Languages != null)
                for (int i = 0; i < vm.Languages.Count; i++)
                {
                    if (consultant.Languages.Count == i)
                        consultant.Languages.Add(vm.Languages[i]);
                    else
                        consultant.Languages.ToList()[i] = vm.Languages[i];
                }
            if (vm.Educations != null)
                for (int i = 0; i < vm.Educations.Count; i++)
                {
                    if (consultant.Educations.Count == i)
                        consultant.Educations.Add(vm.Educations[i]);
                    else
                        consultant.Educations.ToList()[i] = vm.Educations[i];
                }
            if (vm.WorkExperiences != null)
                for (int i = 0; i < vm.WorkExperiences.Count; i++)
                {
                    if (consultant.WorkExperiences.Count == i)
                        consultant.WorkExperiences.Add(vm.WorkExperiences[i]);
                    else
                        consultant.WorkExperiences.ToList()[i] = vm.WorkExperiences[i];
                }

            if (vm.CompetenceAreas != null)
                for (int i = 0; i < vm.CompetenceAreas.Count; i++)
                {
                    if (consultant.CompetenceAreas.Count == i)
                        consultant.CompetenceAreas.Add(vm.CompetenceAreas[i]);
                    else
                        consultant.CompetenceAreas.ToList()[i] = vm.CompetenceAreas[i];
                }

            string uploadDir = Server.MapPath(Request.ApplicationPath) + "FileArea\\ConsultantImages\\";
            foreach (string f in Request.Files.Keys)
            {
                var filePath = Path.Combine(uploadDir, Path.GetFileName(Request.Files[f].FileName));
                if (Request.Files[f].ContentLength > 0)
                {
                    Request.Files[f].SaveAs(filePath);
                    consultant.Image = filePath;
                }

            }
            return consultant;
        }

这是荒谬的,它可能是由于我的无能,但我需要知道如何正确地做到这一点。就在回答使用视图模型显然是不够的,因为那是什么让我进入这个麻烦的开始。我想简单的实体对象为模型,但没有EntityCollection已经初始化错误的简单性。我该如何解决这个问题?

This is absurd, and it's probably due to my incompetence, but I need to know how to do this properly. Just the answer "use a ViewModel" obviously won't suffice, because that's what got me into this trouble to begin with. I want the simplicity of the simple entity object as model but without the "EntityCollection has already been initialized" error. How do I get around this?

当然,如果我只是在做视图模型战略走错了路,在该建议也欢迎,但主要是我想知道,如果我做了简单的NerdDinner范例简单对象的方法是什么原因造成这个错误。请注意也有问题的看法是限制到该站点的授权用户。我很想做正确的方式,但如果使用的ViewModels意味着有code,它是此难以维持,我会放弃它...

Of course, if I'm just doing the ViewModel strategy the wrong way, suggestions on that are welcome too, but mainly I want to know what is causing this error if I do it the simple "NerdDinner" simple object way. Please keep in mind also that the View in question is restricted to authorized users of the site. I would love to do it the "correct" way, but if using ViewModels implies having code that is this hard to maintain, I'll forgo it...

请帮帮忙!

更新:

原来这code甚至不工作。我打电话编辑更新值后,只是检查,它不更新它们。因此,只有创建部分作品。

Turns out this code doesn't even work. I just checked after calling Edit to update values, and it doesn't update them. So only the Create part works.

这是不工作的一部分:

consultant.Programs.ToList()[i] = vm.Programs[i];

我有点预感我不能用了ToList并更新EntityCollection的项目。但是,这使得更难。所以,现在我不知道如何直接与实体,我想preFER(见上文)做到这一点。我不知道如何得到这个视图模型的东西的工作,更不用说得到它干净...

I sort of had a hunch I couldn't use ToList and update an item in the EntityCollection. But this makes it even harder. So now I don't know how to do it with the entity directly, which I would prefer (see above). And I don't know how to get this ViewModel stuff working, let alone get it clean...

任何想法?一定有什么东西真的错了这里,而且我希望有人会发现我是多么刚刚错过了简单的东西,变成这一切code发挥得淋漓尽致!

Any ideas? There must be something really wrong here, and I'm hoping someone will spot how I've just missed something simple that turns all of this code on its head!

推荐答案

好了,在我的经验,EF的东西不容易很好地在电线上,句号(意使用时上场,这不是一个很好的传球格式在无论你在MVC或WCF,或其他)的数据。这是一个问题EF,对我来说,不是一个MVC问题,因为你与直接用你的EF模型遇到问题需要做瓦特/他们是如何在EF ObjectContext的跟踪。我被告知,有到该解决方案涉及重新连接传递的实体,但我发现它是更多的麻烦比它的价值;这是因为有其他原因,大多数人说使用的ViewModels在这种情况下。

Ok, so in my experience the EF stuff doesn't easily play nicely when used on the wire, full stop (meaning, it's not a good format for passing data in whether you're in MVC or WCF, or whatever). It's an EF issue, to me, not a MVC issue because the problem you're experiencing with the direct use of your EF models has to do w/ how they're tracked in the EF objectcontext. I've been told that there's solutions to that involving re-attaching the passed entity, but I've found it to be more trouble than it's worth; as have others which is why most folks say "use viewmodels" for your input parameters in this situation.

我同意你的$ C $上面c是一种不愉快的,有一对夫妇的方式来解决这个问题。首先,请 AutoMapper ,这有助于很多,你可以跳过定义明显(例如,当这两种模式有一个简单的财产像兴田同一类型和放大器的名;名称

I agree that your code above is kind unpleasant, there's a couple ways to fix it. First, check out AutoMapper, which helps a lot in that you can skip defining the obvious (e.g. when both models have a simple property like "Name" of hte same type & name.

二,你在做什么瓦特/环路是有点过呢。你不应该假设被张贴名单与客户端相同的顺序等作为EF正在跟踪名单(名单,而在提及到你的程序,等等)。相反,认为这可能会发生,并解释这些的情景。我将使用程序作为一个例子。

Second, what you're doing w/ the loops is a bit off anyway. You should not assume that your list being posted from the client is the same order, etc as the list that EF is tracking (lists, rather; referring to your Programs, etc). Instead, think of the scenarios that might occur and account for those. I'll use Programs as an example.

1)的顾问有一个计划,但有关该计划的详细信息已经改变。
2)一个顾问不具有一个程序,是在视图模型
2A)程序已经存在于数据库中的某个地方,只是没有这个顾问的一部分
2B)的计划是新的。
3)顾问有一个计划,不是在视图模型(您目前没有考虑的东西)。

1) a consultant has a program, but details about that program have changed. 2) a consultant does not have a program that is in the viewmodel 2a) the program already exists in the database somewhere, just not part of this consultant 2b) the program is new. 3) a consultant has a program that's not in the viewmodel (something you don't currently account for).

我不知道你想在每个这样的情况下发生的(即是视图模型完整,规范的,或者是实体模型,在更新过程中?)什么,但让我们说你是循环您的视图模型的计划你上面做的。对于方案1(这似乎是你的主要问题),你会想要做这样的事情(使用AutoMapper):

I don't know what you want to have happen in each of those cases (i.e. is the viewmodel complete and canonical, or is the entity model, during an update?), but let's say you're looping over your viewmodel's Programs as you do above. For the scenario 1 (which seems to be your main problem), you will want to do something like (using AutoMapper):

var updated = vm.Programs[i];    
var original = consultant.Programs.SingleOrdefault(p=>p.ID == uppdated.ID);
Mapper.Map(updated,original);
yourEfContext.SaveChanges(); // at some point after this, doesn't have to be inside the loop

编辑:
另外一个想法,可能对你有用的是,我当你获取你的顾问从数据库中(不知道什么机制使用该),请确保您调用包括关于你要更新以及集合。否则,每个迭代那些你做将是另一个往返到数据库中,这显然如果你只是用你可以避免包含跃跃欲试加载它们都在一杆。

one other thought that might be useful to you is that I when you fetch your consultant out of the database (not sure what mechanism you use for that), make sure you call Include on the collections that you're going to update as well. Otherwise, each of those iterations you do will be another round-trip to the database, which obviously you could avoid if you just used Include to eager-load them all in one shot.

这篇关于&QUOT; EntityCollection已经初始化&QUOT;误差实体在Asp.Net MVC模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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