实体框架 4. 连接表。不需要任何操作时实体框架执行插入

发布于 2024-11-05 11:40:10 字数 3088 浏览 0 评论 0原文

我有一个数据库设置如下: -

Person Table  
Hobby Table
Game Table  
GameInfo Table  

Person [1 - M] Hobby [1 - M] Game [M - 1] GameInfo

Game 只是来自 Hobby 的加入到 GameInfo

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

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

我已经查看了 Entry().State 等,但问题是我处理 Person 的更新的位置在上下文之外。

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

编辑 1:代码示例 - 编辑 2 的排序

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

- 上下文配置

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

I have a database setup with the following: -

Person Table  
Hobby Table
Game Table  
GameInfo Table  

Person [1 - M] Hobby [1 - M] Game [M - 1] GameInfo

Game is just a join from Hobby to GameInfo

I am having an issue whereby I would fetch Person which has a Collection<Game> and add to this collection (i.e. I am just updating links, not wanting to insert new GameInfo).

Upon Calling SaveChanges() EntityFramework will insert the links AS WELL AS inserting new GameInfo, which is not my desired result.

I have looked at Entry().State etc but the problem is where I am handling the updates of my Person is outside of the context.

I am basically fetching a Person creating a new Game with Ids that I know exist already and then calling the SaveChanges() and would expect that it would just insert into the Game Table, not the GameInfo table

EDIT 1: Code Sample - sort of

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

EDIT 2 - Context configuration

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

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

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

发布评论

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

评论(2

清晰传感 2024-11-12 11:40:10

好吧,我仍然不明白你在哪里使用 GameInfo - 你的描述绝对与你的代码不符。通过查看您的代码,我猜问题出在这样的代码片段中:

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。如果您想添加现有的游戏,您必须执行以下操作:

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

Well I still don't see where you work with GameInfo - your description absolutely doesn't correspond with your code. By looking at your code I guess the problem will be in the snippet like this:

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

This will always insert a new Game - you told EF to insert a new Game. If you want to add existing Game you must do:

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);
    }
}
鸠书 2024-11-12 11:40:10

我认为我在这里犯的错误是,我正在处理 DataGame,而实际上我应该处理的是一个 POCO 类来表示 DataGameHobby 就像一个HobbyGame POCO。

I think the mistake I have made here is that I am dealing with DataGame when really what I should be dealing with is a POCO class to represent the "join" between DataGame and Hobby Like a HobbyGame POCO.

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