EF4.0 - 有没有办法在调试期间查看哪些实体附加到哪些 ObjectContext?

发布于 2024-11-11 16:35:18 字数 3205 浏览 6 评论 0原文

这是我的

我正在尝试使用 几个月前朱莉·勒曼给了我解决方案。我目前正在使用以下内容生成一个预先附加到我的 ObjectContext 的新游戏实体:

Game game = _gameRepository.GetGame(formData.GameID);
AutoMapper.Mapper.Map<AdminGameEditModel, Game>(formData, game);

在存储库中,我尝试将游戏附加到 OC,并将其状态设置为“已添加”,就像她建议的那样,执行以下操作:

public Game GetGame(int id)
{
    if (id > 0)
    {
        return _siteDB.Games.Include("Genre").Include("Platforms").SingleOrDefault(g => g.GameID == id);
    }
    else
    {
        Game game = _siteDB.Games.CreateObject();
        _siteDB.Games.AddObject(game);
        return game;
    }
}

现在,为了清楚起见,这是我的控制器的完整构造函数:

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)
            {
                Platform newPlat = _gameRepository.GetPlatform(platId);
                d.Platforms.Add(newPlat);
            }
        })
        .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());
}

如您所见, _gameRepository 应该是相同的,因为它是在控制器构造时创建的。反过来,这意味着游戏和平台的 _gameRepository 的 OC 应该相同。然而,在这种情况下,我仍然收到一个异常,其中指出:

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

肯定发生了一些奇怪的事情,这就是为什么我想知道我是否可以真正跟踪实体实际附加到哪个 ObjectContext。它们都应该附加到同一个 OC,但例外情况另有说明。

也许这与我使用 Ninject(普通版本,不是 MVC 定制版本)在控制器中注入存储库有关。无论问题是什么,它似乎都不明显。任何帮助将非常感激。

编辑:存储库的 ObjectContext:

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB = new HGEntities();

    // rest of class code
}

Ninject 绑定:

private class HandiGamerServices : NinjectModule
{
    public override void Load()
    {
        Bind<IArticleRepository>().To<HGArticleRepository>().InRequestScope();
        Bind<IGameRepository>().To<HGGameRepository>().InRequestScope();
        Bind<INewsRepository>().To<HGNewsRepository>().InRequestScope();
        Bind<ErrorController>().ToSelf().InRequestScope();
    }
}

This is in continuation with my problem here.

I'm trying to use the solution Julie Lerman gave me a few months ago. I'm currently using the following to generate a new Game entity pre-attached to my ObjectContext:

Game game = _gameRepository.GetGame(formData.GameID);
AutoMapper.Mapper.Map<AdminGameEditModel, Game>(formData, game);

In the repository, I try to attach the Game to the OC with its state set to 'Added' like she suggested by doing the following:

public Game GetGame(int id)
{
    if (id > 0)
    {
        return _siteDB.Games.Include("Genre").Include("Platforms").SingleOrDefault(g => g.GameID == id);
    }
    else
    {
        Game game = _siteDB.Games.CreateObject();
        _siteDB.Games.AddObject(game);
        return game;
    }
}

Now, for clarity's sake, here's my controller's constructor in its entirety:

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)
            {
                Platform newPlat = _gameRepository.GetPlatform(platId);
                d.Platforms.Add(newPlat);
            }
        })
        .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());
}

As you can see, the _gameRepository should be the same, since its created on controller construction. This, in turn, means that the _gameRepository's OC should be the same for both the Game and Platforms. Yet, with that being the case, I'm still getting an exception which states:

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

Something screwy is definitely going on, which is why I want to know if I can actually trace which ObjectContext the entities are actually attached to. They should all be attached to the same OC, but the exception claims otherwise.

Maybe it has something to do with me using Ninject (the vanilla version, not the MVC tailored version) to inject the repositories in the controller. Whatever the problem is, it hardly seems obvious. Any help would be greatly appreciated.

EDIT: Repository's ObjectContext:

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB = new HGEntities();

    // rest of class code
}

Ninject bindings:

private class HandiGamerServices : NinjectModule
{
    public override void Load()
    {
        Bind<IArticleRepository>().To<HGArticleRepository>().InRequestScope();
        Bind<IGameRepository>().To<HGGameRepository>().InRequestScope();
        Bind<INewsRepository>().To<HGNewsRepository>().InRequestScope();
        Bind<ErrorController>().ToSelf().InRequestScope();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七禾 2024-11-18 16:35:18

您可以通过以下方式询问 ObjectContext 是否具有对某个对象的引用:

ObjectStateEntry ose;
bool isInContext = someContext.ObjectStateManager.TryGetObjectStateEntry(someObject, out ose);

You can ask the ObjectContext if it has a reference to a certain object by:

ObjectStateEntry ose;
bool isInContext = someContext.ObjectStateManager.TryGetObjectStateEntry(someObject, out ose);
厌倦 2024-11-18 16:35:18

有问题的部分是

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB = new HGEntities();

    // rest of class code
}

我相信所有存储库在创建时都会创建自己的新上下文。相反,您应该使用构造函数注入

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB;

    public HGGameRepository(HGEntities entities)
    {
          _siteDB= entities
    }
}

然后在您的 Ninject 模块中包含此内容

Bind<HGEntities>().ToSelf().InRequestScope();

这样您的存储库将共享相同的上下文。

The problematic part is this

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB = new HGEntities();

    // rest of class code
}

I believe all your Repositories create new Contexts of their own when created. Instead of this you should use constructor injection

public class HGGameRepository : IGameRepository
{
    private HGEntities _siteDB;

    public HGGameRepository(HGEntities entities)
    {
          _siteDB= entities
    }
}

Then in your Ninject module include this

Bind<HGEntities>().ToSelf().InRequestScope();

This way your repositories will share the same context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文