试图将新的EF4实体附加到ObjectContext,同时其实体集合实体已附加的问题 [英] Problems trying to attach a new EF4 entity to ObjectContext while its entity collection entities are already attached

查看:213
本文介绍了试图将新的EF4实体附加到ObjectContext,同时其实体集合实体已附加的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个ASP.NET MVC 2项目正在慢慢地杀死我

罢工>我正在尝试采取表单数据,并将其转换为实体以创建或更新,具体取决于情况的上下文。最相关的部分(伪代码):

 实体游戏
标量属性
EntityCollection<平台>平台

基本工作流程是:



表单数据 - >绑定到DTO的模型 - >使用AutoMapper将DTO映射到EF4实体。



一切都可以正常运行 - 我需要创建或使用DTO中包含的原始整数索引数据更新Game实体的Platforms EntityCollection。所以,这是我一直在尝试的,这不行:

  public AdminController(IArticleRepository articleRepository,IGameRepository gameRepository,INewsRepository newsRepository )
{
_articleRepository = articleRepository;
_gameRepository = gameRepository;
_newsRepository = newsRepository;

Mapper.CreateMap&AdminGameEditModel,Game>()
.BeforeMap((s,d)=>
{
if(d.Platforms.Count> ; 0)
{
平台[] existing = d.Platforms.ToArray();

foreach(现有的var平台)
{
d .platforms.Remove(plat);
}
}

foreach(s.PlatformIDs中的var platId)
{
var newPlat = _gameRepository.GetPlatform (platId);

d.Platforms.Add(newPlat); //< - 其中chokes
}
})
.ForMember(dest = > dest.BoxArtPath,opt => opt.Ignore())
.ForMember(dest => dest.IndexImagePath,opt => opt.Ignore())
.ForMember(dest = > dest.Cons,opt => opt.MapFrom(src => String.Join(|,src.Cons)))
.ForMember(dest => dest.Pros,o pt => opt.MapFrom(src => String.Join(|,src.Pros)))
.ForMember(dest => dest.LastModified,opt => opt.UseValue(DateTime.Now))
.ForMember(dest => dest.Platforms,opt => opt.Ignore());
}

具体来说,我在上面突出显示的一行出现异常其中说:


两个对象之间的关系无法定义,因为它们附加到不同的ObjectContext对象。


一些研究告诉我,这是可以预期的,因为我的新鲜的Game对象没有与它相关联的ObjectContext,并且一个空的上下文被认为是一个单独的上下文。有关更多信息,请参阅来自Julie Lerman的简要说明。 / p>

好吧,所以我是一个勇敢的人,我想我只能用ObjectContext注册我的游戏,一切都会被修复。所以,我试过:

 游戏游戏=新游戏(); 
_gameRepository.RegisterGame(游戏);

其中RegisterGame简单:

  public void RegisterGame(game game)
{
_siteDB.Games.AddObject(game);
}

不幸的是,这没有办法。同样的例外也被抛在同一点上。



所以,看来我需要把每个平台的EntityKey添加到我的EntityCollection中。只有问题是,我不知道该怎么做。



所以,任何想法?






编辑:排序进度。我尝试只添加平台实体的EntityKeys,如下所示:

  Mapper.CreateMap< AdminGameEditModel,Game>()
.BeforeMap((s,d)=>
{
if(d.Platforms.Count> 0)
{
Platform [] existing = d.Platforms $ to $($)


$ b foreach(var platId in s.PlatformIDs)
{
var newPlat = _gameRepository.GetPlatform(platId);

d.Platforms.Add(new Platform {EntityKey = newPlat.EntityKey});
}
})

它会删除两个不同的ObjectContexts异常。问题是,如果我尝试添加或附加新的Game实体到我的上下文,我得到以下异常:


一个对象ObjectStateManager中已经存在相同的密钥。 ObjectStateManager无法跟踪具有相同键的多个对象。


不幸的是,异常没有指定 对象它是,但我敢打赌它是Platform对象之一,因为它们已经存在,我只是试图在两者之间建立一种新的关系。



所以,问题仍然存在:一个人怎么做一个新的实体,并用现有的实体填充它的EntityCollection<>属性?我不可能是唯一一个想要创建一个新实体并创建新的实体与现有实体之间的多对多关系的人,对吧?

解决方案

我使用 Julie Lerman的原始解决方案。我没有使用原始的DTO解决方案来分离/重新附加我的平台,所以我以为我不需要在这里。无论如何,看起来我需要对如何处理ObjectContext做更多的研究。


This is somewhat complicated to explain, so please bear with me.

I have an ASP.NET MVC 2 project that is slowly killing me in which I'm trying to take form data and translate it into entities to create or update, depending on the context of the situation. The most relevant parts (pseudo-code):

Entity Game
    Scalar properties
    EntityCollection<Platform> Platforms

And the basic workflow is:

Form data -> model bound to a DTO -> mapping the DTO to an EF4 entity with AutoMapper.

It all works well with one exception - I need to create or update the Game entity's Platforms EntityCollection with the raw integer index data contained in the DTO. So, here's what I've been trying, which does not work:

public AdminController(IArticleRepository articleRepository, IGameRepository gameRepository, INewsRepository newsRepository)
{
    _articleRepository = articleRepository;
    _gameRepository    = gameRepository;
    _newsRepository    = newsRepository;

    Mapper.CreateMap<AdminGameEditModel, Game>()
        .BeforeMap((s, d) =>
        {
            if (d.Platforms.Count > 0)
            {
                Platform[] existing = d.Platforms.ToArray();

                foreach (var plat in existing)
                {
                    d.Platforms.Remove(plat);
                }
            }

            foreach (var platId in s.PlatformIDs)
            {
                var newPlat = _gameRepository.GetPlatform(platId);

                d.Platforms.Add(newPlat); // <-- where it chokes
            }
        })
        .ForMember(dest => dest.BoxArtPath, opt => opt.Ignore())
        .ForMember(dest => dest.IndexImagePath, opt => opt.Ignore())
        .ForMember(dest => dest.Cons, opt => opt.MapFrom(src => String.Join("|", src.Cons)))
        .ForMember(dest => dest.Pros, opt => opt.MapFrom(src => String.Join("|", src.Pros)))
        .ForMember(dest => dest.LastModified, opt => opt.UseValue(DateTime.Now))
        .ForMember(dest => dest.Platforms, opt => opt.Ignore());
}

To be specific, I'm getting an exception at the line I highlighted above which says:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

Some research tells me that this is to be expected, as my fresh Game object has no ObjectContext that it's associated with, and a null context is considered to be a separate context. See this brief explanation from Julie Lerman for more.

Okay, so being the intrepid person I am, I figured I would simply be able to register my game with the ObjectContext and everything would be fixed. So, I tried:

Game game = new Game();
_gameRepository.RegisterGame(game);

Where RegisterGame is simply:

public void RegisterGame(Game game)
{
    _siteDB.Games.AddObject(game);
}

Unfortunately, that did not work. The same exception is being thrown at the same point.

So, it looks like I'll have to add each Platform's EntityKey to my EntityCollection. Only problem is, I'm not sure how to do it.

So, any ideas?


EDIT: Progress of a sort. I tried adding just the EntityKeys of the Platform entities, like so:

Mapper.CreateMap<AdminGameEditModel, Game>()
    .BeforeMap((s, d) =>
    {
        if (d.Platforms.Count > 0)
        {
           Platform[] existing = d.Platforms.ToArray();

           foreach (var plat in existing)
           {
                d.Platforms.Remove(plat);
           }
        }

        foreach (var platId in s.PlatformIDs)
        {
            var newPlat = _gameRepository.GetPlatform(platId);

            d.Platforms.Add(new Platform { EntityKey = newPlat.EntityKey });
        }
    })

And it removes the 'two different ObjectContexts' exception. The problem is that I'm getting the following exception if I try to add or attach the new Game entity to my context:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

Unfortunately, the exception doesn't specify which object it is, but I'm betting it's one of the Platform objects, since they already exist and I'm merely trying to forge a new relationship between the two.

So, the question remains: how the hell does one make a new entity and populate its EntityCollection<> property with existing entities? I can't be the only person who ever wanted to create a new entity and create new many-to-many relationships between it and existing entities, right?

解决方案

I got it to work by using Julie Lerman's original solution. I didn't have to detach/re-attach my platforms with my original, pre-DTO solution, so I thought I didn't need to here. In any event, it looks like I need to do more research on how to handle the ObjectContext.

这篇关于试图将新的EF4实体附加到ObjectContext,同时其实体集合实体已附加的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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