Entity Framework POCO с внешними ключами

Мой вопрос лучше объяснить с помощью примера кода. Я использую POCO с прокси-серверами отслеживания изменений, которые по умолчанию генерируются генератором C# POCO. Пожалуйста, смотрите ниже.

Предположим, у вас есть Movie, MusicDirector и Director в базе данных, и отношения между ними: Director и MusicDirector могут управлять несколькими фильмами, а у фильма может быть только один Director и MusicDirector. Поскольку я новый пользователь и не могу публиковать изображения, вот моя структура базы данных.

Таблица фильмов имеет MovieId, Name, MusicDirectorId, DirectorId

Таблица директоров имеет DirectorId, Name

Таблица MusicDirector имеет MusicDirectorId, Name

Вот ссылка на схему. http://i.stack.imgur.com/ce49r.png.

Я пытаюсь вставить новый фильм, а режиссер и музыкальный директор «уже существуют» в базе данных. Ниже мой код.

Movie movie = new Movie();            
        movie.Name = "Movie1";
        movie.Director = new Director() { Name = "DirectorA" };           
        movie.MusicDirector = new MusicDirector() { Name = "MusicDirectorA" };

        using (TestEFEntities ctx = new TestEFEntities())
        {
            movie.Director = ctx.Directors.Where(x => x.Name == movie.Director.Name).FirstOrDefault();
            movie.MusicDirector = ctx.MusicDirectors.Where(x => x.Name == movie.MusicDirector.Name).FirstOrDefault();                                    
            ctx.Movies.AddObject(movie);                    
            ctx.SaveChanges();
        }

Теперь, когда я это делаю, запись MusicDirector снова добавляется, хотя она перезаписывается записью из БД. Вы можете подумать, почему я сохраняю эту строку movie.Director = new Director() { Name = "DirectorA" }; изначально это приложение Asp.net MVC, в котором объект Movie связан с именами режиссера и музыкального директора, которые добавляет пользователь. Итак, первые 4 строки выполняются MVC неявно, а все остальные строки находятся на уровне сервиса. Я что-то упустил, так как это очень простой сценарий, и фреймворк должен с ним справиться? Конечно, одним из решений этой проблемы является создание нового объекта Movie и назначение записей из базы данных, чего я не хочу делать, поскольку мне нужно скопировать все свойства из объекта фильма, отправленного контроллером. Как я могу решить эту проблему?

Также это корректно работает в объектах с самостоятельным отслеживанием. Является ли это каким-то ограничением для POCO, и было бы здорово, если бы кто-нибудь мог объяснить его поведение?


person Jonna    schedule 12.11.2010    source источник


Ответы (1)


Если вы используете POCO, ваш код должен работать так, как вы ожидали. В качестве альтернативы вы можете попытаться заполнить FK вместо назначения всего объекта следующим образом:

using (TestEFEntities ctx = new TestEFEntities())
{
    movie.DirectorID = ctx.Directors
        .Where(x => x.Name == movie.Director.Name).First().DirectorID;

    movie.MusicDirectorID = ctx.MusicDirectors
        .Where(x => x.Name == movie.MusicDirector.Name).First().MusicDirectorID;

    ctx.Movies.AddObject(movie);                    
    ctx.SaveChanges();
}
person Morteza Manavi    schedule 12.11.2010
comment
Я использую POCO и, следовательно, не имею свойства DirectorReference. - person Jonna; 12.11.2010
comment
Да, извините, вы упомянули об этом, а я не заметил. Итак, как насчет заполнения FK, как я описал в своем обновленном ответе? - person Morteza Manavi; 12.11.2010
comment
Как бы вы сделали это, используя DbContext в EF CTP 5 и генератор Ado.net DbContext? Кода исправления нет, поэтому установка DirectorId не очищает Director. Всегда ли установка movie.Director = null после установки DirectorId моей единственной опции? - person Jonna; 28.01.2011