【问题标题】:Entity Framework 4. Join Tables. Entity Framework perfoming an Insert when no action is required实体框架 4. 连接表。无需操作时执行插入的实体框架
【发布时间】:2011-05-10 21:41:17
【问题描述】:

我有以下数据库设置:-

Person Table  
Hobby Table
Game Table  
GameInfo Table  

人物 [1 - M] 爱好 [1 - M] 游戏 [M - 1] 游戏信息

Game 只是从HobbyGameInfo 的连接

我遇到了一个问题,我将获取具有Collection<Game>Person 并添加到此集合中(即我只是在更新链接,不想插入新的GameInfo)。

在调用SaveChanges() 时,EntityFramework 将插入链接以及插入新的GameInfo,这不是我想要的结果。

我查看了 Entry().State 等,但问题是我处理 Person 更新的位置超出了上下文。

我基本上是在获取一个Person 创建一个新的Game,其ID 我知道已经存在,然后调用SaveChanges() 并希望它只会插入Game 表,而不是GameInfo 表

编辑 1:代码示例 - 有点

public void Save(Profile profile)
{
    using (GDContext context = GetContext())
    {
        DataProfile dataProfile = context.Profiles.Single(u => u.ProfileId == profile.Id);
        ProfileHandler.HandleDataModelChanges(dataProfile, profile);
        context.SaveChanges();
    }
}

public override void HandleDataModelChanges(DataProfile dataModel, Profile model)
{
    dataModel.ProfileId = model.Id;
    dataModel.FirstName = model.FirstName;
    dataModel.LastName = model.LastName;
    dataModel.DateOfBirth = model.DateOfBirth;
    dataModel.Email = model.Email;

    foreach(var hobby in model.Hobbies)
    {
        DataHobby dataHobby = dataModel.Hobbies.SingleOrDefault(p => p.HobbyId == hobby.HobbyId);

        if (dataHobby == null)
        {
            dataHobby = new DataHobby();
        }

        HobbyHandler.HandleDataModelChanges(dataHobby, hobby);
    }
}

public override void HandleDataModelChanges(DataHobby dataModel, Hobby model)
{
    dataModel.HobbyId = model.Id;

    HandleGames(dataModel, model);

    HandleCrafts(dataModel, model);

    HandleCollections(dataModel, model);
}

private void HandleGames(DataHobby dataModel, Hobby model)
{
    IEnumerable<DataGame> gamesToRemove = dataModel.Games.Where(g => !model.Games.Any(ds => ds.Id == g.GameId)).ToArray();

    foreach (var game in gamesToRemove)
    {
        dataModel.Games.Remove(game);
    }

    foreach (var game in model.Games)
    {
        if (!dataModel.Games.Any(e => e.GameId == game.Id))
        {
            DataGame dataGame = new DataGame();
            dataGame.GameId = game.Id;
            dataGame.GameName = game.Name;

            dataModel.Games.Add(dataGame);
        }
    }
}

编辑 2 - 上下文配置

this.Configuration.LazyLoadingEnabled = false;
this.Configuration.AutoDetectChangesEnabled = true;

public GameInfoConfiguration()
{
    HasKey(x => x.GameId);
    ToTable("GameData");
}

public PersonConfiguration()
{
    HasKey(x => x.PersonId);

    ToTable("Person");
}

public HobbyConfiguration()
{
    HasKey(x => x.HobbyId);

    HasRequired(x => x.Person).WithMany(x => x.Hobbies);

    HasMany(x => x.Games).WithMany(g => g.Hobbies).Map(x => x.MapLeftKey("HobbieId").MapRightKey("GameId").ToTable("PersonGame"));

    ToTable("HobbyGame");
}

【问题讨论】:

  • 我认为显示一些代码 sn-p 将使场景更加清晰,然后尝试解释它。显示如何创建/检索实体以及如何处理上下文 + 插入实体的小代码示例。

标签: c# entity-framework entity-framework-4


【解决方案1】:

好吧,我仍然看不到您在哪里使用 GameInfo - 您的描述绝对与您的代码不符。通过查看您的代码,我猜问题出在 sn-p 中,如下所示:

foreach (var game in model.Games)
{
    if (!dataModel.Games.Any(e => e.GameId == game.Id))
    {
        DataGame dataGame = new DataGame();
        dataGame.GameId = game.Id;
        dataGame.GameName = game.Name;

        dataModel.Games.Add(dataGame);
    }
}

这将始终插入一个新的Game - 你告诉 EF 插入一个新的Game。如果你想添加现有的Game,你必须这样做:

foreach (var game in model.Games)
{
    if (!dataModel.Games.Any(e => e.GameId == game.Id))
    {
        DataGame dataGame = new DataGame();
        dataGame.GameId = game.Id;
        dataGame.GameName = game.Name;

        context.Games.Attach(dataGame); // Now the context knows that it is not a new entity 
        dataModel.Games.Add(dataGame);
    }
}

【讨论】:

  • 谢谢,是的,我一直在阅读有关此 Attach() 方法的信息,问题是我在构建 POCO 类时没有对上下文的引用,我已经做了类似的事情this 在之前的 entityFramework 版本中没有看到为什么这种行为发生了变化。
  • 只是回答我的解释与我的代码不匹配的查询。问题是我一开始就试图简化我的问题。
  • 我认为在以前的版本中是一样的。仅当从数据库加载现有对象而不是在代码中创建新实例时,才需要使用 Attach
  • 好吧,但是如果您进行简化,您的代码必须与简化相对应 = 您必须将代码减少到不起作用的部分。
  • 刚刚意识到 GameInfo 去了哪里...将是 model.Games 中的 var :) GameInfo 是我的“DataGame”的“DomainModel”...
【解决方案2】:

我认为我在这里犯的错误是我正在处理DataGame,而我真正应该处理的是一个 POCO 类来表示 DataGameHobby 之间的“连接”,就像 @987654324 @POCO。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多