Entity Framework 4. Соединение таблиц. Entity Framework выполняет вставку, когда никаких действий не требуется - PullRequest
0 голосов
/ 09 мая 2011

У меня есть база данных со следующими настройками: -

Person Table  
Hobby Table
Game Table  
GameInfo Table  

Персона [1 - M] Хобби [1 - M] Игра [M - 1] GameInfo

Gameэто просто соединение от Hobby до GameInfo

У меня возникла проблема, из-за которой я бы выбрал Person с Collection<Game> и добавил бы в эту коллекцию (т.е. я просто обновляю ссылки, а нежелая вставить новый GameInfo).

После вызова SaveChanges() EntityFramework вставит ссылки КАК ХОРОШО, КАК вставляет новый GameInfo, что не является моим желаемым результатом.

Я смотрелat Entry (). State и т. д., но проблема в том, что я обрабатываю обновления моего Person вне контекста.

В основном я получаю Person, создавая новый Game с идентификаторамия знаю, что уже существует и затем вызывает 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);
        }
    }
}

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

Ответы [ 2 ]

2 голосов
/ 09 мая 2011

Ну, я до сих пор не понимаю, где вы работаете с 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.Если вы хотите добавить существующий 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);
    }
}
0 голосов
/ 10 мая 2011

Я думаю, что ошибка, которую я здесь сделал, заключается в том, что я имею дело с DataGame, когда на самом деле я должен иметь дело с классом POCO, представляющим "соединение" между DataGame и Hobby Как HobbyGame POCO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...