Коллекция в модели структуры сущностей не обновляется - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть пара простых моделей.Модель PlaylistEntry и модель Playlist, которая содержит коллекцию моделей PlaylistEntry.

Список воспроизведения:

    public class Playlist
    {
        private ICollection<PlaylistEntry> playlistEntries;

        public int PlaylistId { get; set; }

        public string Name { get; set; }

        public virtual ICollection<PlaylistEntry> PlaylistEntries
        {
            get => this.playlistEntries ?? (this.playlistEntries = new HashSet<PlaylistEntry>());
            set => this.playlistEntries = value;
        }
    }

PlaylistEntry

    public class PlaylistEntry
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PlaylistEntryId { get; set; }

        public string FilePath { get; set; }

        [ForeignKey("Playlist")]
        public int PlaylistId { get; set; }

        [Required]
        public Playlist Playlist { get; set; }
    }

Когда я добавляю PlaylistEntry в список воспроизведенияв отсоединенном состоянии я ожидаю, что когда я прикреплю и сохраню изменения, изменения в списке PlaylistEntries также будут сохранены.Они не сохраняются, и список пуст.

Вот мой код:

    var playlist = new Playlist { Name = "My first playlist" };
    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Add(playlist);
        context.SaveChanges();
    }

    playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "lkdfj", PlaylistId = playlist.PlaylistId });

    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Attach(playlist);
        context.Entry(playlist).State = EntityState.Modified;
        context.SaveChanges();
    }

    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Include(x => x.PlaylistEntries).ToList();
    }

Этот последний вызов ToList возвращает созданный мной список воспроизведения, но коллекция PlaylistEntries на нем пуста.

Может кто-нибудь заметить, что я делаю неправильно или предложить другое решение, пожалуйста?Я потратил около 7 часов на это и не могу понять, насколько я понимаю.

Ответы [ 3 ]

0 голосов
/ 09 февраля 2019

Вам не хватает функции, как работает Context Cache.Когда вы присоединяете объект (либо вручную, либо запрашивая объект из базы данных) к контексту, он просматривает структурой объекта на предмет изменений и отслеживает эти изменения.

Вы добавиливозражать против праведности, а затем добавить его в контекст.Entity Framework теперь следит за изменениями, чтобы выполнить любую дополнительную работу. Все объекты, добавленные таким образом, помечаются как без изменений .Пометка родительского элемента изменено не помечает свойства навигации как изменено .

Вы можете добавить объект в свойство внутри контекста:

using (var context = new MusicPlayerContext())
{
    Console.WriteLine("Save PlayList 2 (in context add)");
    context.Playlists.Attach(playlist3);
    playlist3.PlaylistEntries.Add(new PlaylistEntry { 
      FilePath = "Entry3", 
      PlaylistId = playlist3.PlaylistId, PlaylistEntryId = 3 
    });
    context.SaveChanges();
}

... ИЛИ помечать записи обоих объектов после присоединения родителя.

using (var context = new MusicPlayerContext())
{
    Console.WriteLine("Save PlayList 2 (full attach)");
    context.Playlists.Attach(playlist2);
    context.Entry(playlist2).State = EntityState.Modified;
    context.Entry(playlist2.PlaylistEntries.First()).State = EntityState.Added;
    context.SaveChanges();
}

В обоих случаях Entity Framework теперь знает, что делать в БД, когда происходит SaveChanges().

DotNetFiddle

0 голосов
/ 09 февраля 2019

Я решил добавить новые записи в список из контекста, как предлагали другие ответы.Если кто-то все еще хочет знать, как заставить это работать в отдельном состоянии, вот как:

var playlist = new Playlist { Name = "My first playlist" };

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Add(playlist);
}

playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "Song7" });
playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "Song8" });

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Add(playlist);
    context.Entry(playlist).State = EntityState.Modified;

    foreach (var entry in playlist.PlaylistEntries)
    {
        context.Entry(entry).State = entry.PlaylistEntryId == 0 ? EntityState.Added : EntityState.Modified;
    }

    context.SaveChanges();
}

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Include(x => x.PlaylistEntries).ToList();
}

На самом деле context.Playlists.Add(playlist) не добавляет новый плейлист.Из того, что я понимаю, он прикрепляет плейлист и все новые записи на нем.Если я не использую Add, я получаю сообщение об ошибке, потому что PlaylistEntryID новых записей по умолчанию установлен на 0.

0 голосов
/ 09 февраля 2019

Всякий раз, когда вы звоните context.SaveChanges(); сразу после добавления только PlayList без PlaylistEntries, Entity Framework отправляет команду в базу данных и сбрасывает состояние контекста.Таким образом, добавление PlaylistEntries к PlayList не даст никакого эффекта.Чтобы вставить PlaylistEntries с Playlist, напишите свой код следующим образом:

var playlist = new Playlist { Name = "My first playlist" };
using (var context = new MusicPlayerContext(stringBuilder))
{
    playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "lkdfj", PlaylistId = playlist.PlaylistId }); // Even you don't need to specify `PlaylistId` here. EF can map it.
    context.Playlists.Add(playlist);
    context.SaveChanges();
}

Надеюсь, это сработает для вас.

...