2016-02-01 5 views
0

Мое приложение использует Code First Entity Framework для управления «Скриптами». Скрипты могут иметь несколько связанных с ними «тегов».Обработка кэшированных объектов

public class Tag 
{ 
    public Guid TagId { get; set; } 
    public string Name { get; set; } 

    public ICollection<Script> Scripts { get; set; } 
} 

public class Script 
{ 
    public Guid ScriptId { get; set; } 
    public string Title { get; set; } 
    ... 

    public ICollection<Tag> Tags { get; set; } = new List<Tag>(); 
} 

Когда приложение запускается, оно загружает список всех тегов и сохраняет ссылки на них. Когда пользователь редактирует скрипт, они могут добавлять и удалять теги в скрипте. Поскольку пользователь добавляет теги, я просто использую script.Tags.Add(tag), чтобы добавить ссылку. Когда я сохраняю скрипт, все работает отлично в первый раз, но при последующих сценариях он заканчивает сохранение нескольких копий старых скриптов и создает повторяющиеся теги.

Я точно знаю, почему это происходит. Когда я звоню Context.SaveChanges, он исправляет ссылки и добавляет скрипт в коллекцию скриптов тега, которые затем сохраняются для следующего сохранения. Что я не знаю, каков правильный способ предотвратить это?

Я придумал несколько решений, которые работают, но ни один из них не кажется идеальным, а некоторые из них имеют серьезные нисходящие стороны. Они также начнут становиться все более сложными и подверженными ошибкам, поскольку приложение растет, и я начинаю иметь больше ассоциаций, подобных этому. Я чувствую, что я должен упустить что-то очевидное.

  • Сбросить .Scripts имущество каждого Tag после сохранения.
  • Перед сохранением отметьте теги как «неизмененные» в контексте, чтобы они не пытались их сохранить.
  • Обновите новую копию каждого Tag в контексте, который используется для сохранения Script.
  • Используйте один Context на весь срок службы приложения.

Каков надлежащий «метод Entity Framework» для обработки этого шаблона?

+0

сотворивший тег - вы или база данных? Создаете ли вы новый тег (экземпляр) каждый раз, когда пользователь добавляет теги? Если это так, это проблема. Если тег уже был создан, вы должны использовать этот экземпляр, чтобы каждый раз добавлять в коллекцию, а не новый экземпляр. – Pawel

+0

Все ключи генерируются базой данных. Список всех тегов загружается из базы данных при запуске приложения, хотя могут быть созданы дополнительные теги. Я добавляю существующие экземпляры тегов к объектам Script (не создавая новые). –

+0

Является ли это веб-или настольным приложением? «Единый« Контекст »на протяжении всей жизни приложения» невозможен в веб-приложении. – krillgar

ответ

1

Я думаю, самым простым решением является сделать класс перехода в класс модели:

public class Tag 
{ 
    public Guid TagId { get; set; } 
    public string Name { get; set; } 
} 

public class ScriptTag 
{ 
    public Guid ScriptId { get; set; } 
    public Guid TagId { get; set; } 
    public virtual Script Script { get; set; } 
    public virtual Tag Tag { get; set; } 
} 

public class Script 
{ 
    public Guid ScriptId { get; set; } 
    public string Title { get; set; } 
    ... 

    public virtual ICollection<ScriptTag> ScriptTags { get; set; } 
     = new List<ScriptTag>(); 
} 

Теперь вы можете манипулировать скрипт-тегов ассоциаций непосредственно без необходимости загружать один Tag объект в контекст, который делает работа. Пользователь может сделать выбор из предварительно загруженных тегов, и вам нужно создать или удалить эти легкие ScriptTag объектов соответственно.

Предположим, у вас есть viewModel объект, содержащий выбранные теги, это способ сделать это:

var script = db.Scripts.Include(s => s.ScriptTags) 
       .Single(s => s.ScriptId == scriptId); 

// Simply replace the `ScriptTags` collection. 
script.ScriptTags.Clear(); 
script.ScriptTags.AddRange(viewModel.Tags.Select(t => new ScriptTag 
    { 
     ScriptId = scriptId, 
     TagId = t.TagId 
    }); 

db.SaveChanges(); 

И это, как получить все теги сценария:

from script in db.Scripts 
where script.ScriptId == scriptId 
from scriptTag in script.ScripTags 
select scriptTag.Tag.Name 
+0

Ах, именно тот тип ответа, который я искал. Я даже не думал о попытке напрямую управлять соединительной таблицей. –

Смежные вопросы