Общие рекомендации по обновлению записи и связанных с ней отношений в Linq-to-SQL - PullRequest
3 голосов
/ 21 сентября 2009

У меня очень общий вопрос об обновлении записи в Linq-to-SQL. Предположим, в моей модели данных у меня есть базовая запись (Таблица - Персона) с отношением m: m к набору Категории (Таблица - Категория). Поэтому у меня есть ассоциативная таблица (PersonCategory), в которой есть внешние ключи как для PersonID, так и для CategoryID.

Когда я хочу обновить Person, у меня могут быть новые записи PersonCategory для добавления, и может потребоваться удалить другие записи PersonCategory. Какова лучшая практика для такой вещи? Хотел бы я удалить все записи в Person.RelatedPersonCategories и затем добавить новые? Является ли LINQ-to-SQL достаточно умным, чтобы договориться о том, какие записи в таблице PersonCategory фактически добавляются, редактируются или удаляются (исходя из потенциальной оценки внешнего ключа)?

Спасибо за любую помощь!

Ответы [ 2 ]

3 голосов
/ 22 сентября 2009

Пока существует активный экземпляр класса DataContext для отслеживания изменений, LINQ to SQL будет рад вставлять / обновлять / удалять строки в связанной таблице каждый раз, когда объекты в коллекция, которая отображает отношение в модели, модифицируется, и вызывается метод DataContext.SubmitChanges () .

Например:

using (var db = new DataContext())
{
    var person = db.Persons.Where(p => p.Name == "Foo").SingleOrDefault();

    if (person != null)
    {
        // Inserts a new row in the 'PersonCategory' table
        // associated to the current 'Person'
        // and to the 'Category' with name 'Employee'
        person.PersonCategories.Add(new PersonCategory() { CategoryName = "Employee" });

        // Updates the 'CategoryName' column in the first row
        // of the 'PersonCategory' table associated to the current 'Person'
        person.PersonCategories(0).CategoryName = "Consultant";

        db.SubmitChanges();
    }
}

Ситуация немного меняется, если вы вносите изменения в объекты модели в режиме " отключен ", то есть когда экземпляр DataContext, который использовался для первоначального создания этих объектов, больше не существует.

В этом случае операции вставки / удаления в связанных таблицах будут отлично работать , когда объект, имеющий измененную коллекцию, присоединен к новому DataContext с таблицей (TEntity) .Attach метод, за которым следует DataContext.SubmitChanges () .

Однако изменения для любого из существующих объектов в коллекции не будут автоматически применены в связанной таблице . Для этого необходимо вручную вызвать метод Table (TEntity) .Attach для каждого объекта в коллекции.
Вот цитата из документации MSDN :

Когда присоединяется новый объект, отложенные грузчики для любого ребенка коллекции (например, EntitySet коллекции объектов из связанные таблицы) инициализируются. Когда SubmitChanges вызывается, члены из дочерних коллекций помещаются в неизмененное состояние. Чтобы обновить участников детской коллекции, вы должны явно вызвать Attach и указать это лицо.

Вот конкретный пример:

// The 'Person' object has been detached
// from the originating 'DataContext', which is now disposed
person.PersonCategories.Add(new PersonCategory() { CategoryName = "Employee" });
person.PersonCategories(0).CategoryName = "Consultant";

using (var db = new DataContext())
{
    // Will detect added and deleted objects
    // in the 'PersonCategory' collection        
    db.Person.Attach(person);

    // Required to detect and modifications
    // to existing objects in the 'PersonCategory' collection
    foreach (var personCategory in person.PersonCategories)
    {
        db.PersonCategory.Attach(personCategory);
    }

    db.SubmitChanges();
}
0 голосов
/ 22 сентября 2009

Исходя из моего опыта, вам не нужно делать здесь ничего особенного. PersonCategory - это просто сущность, и вы добавляете или удаляете экземпляры из связанного экземпляра таблицы в контексте данных, как и для любой другой сущности, с помощью InsertOnSubmit() и DeleteOnSubmit(). Обновления существующих PersonCategory объектов обрабатываются системой отслеживания изменений.

Вам, конечно, не нужно сначала удалять все элементы, а затем добавлять новые обратно.

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

Например,

  • Person будет иметь EntitySet<PersonCategory>

  • PersonCategory будет иметь EntityRef<Person> и EntityRef<Category>

  • Category будет иметь EntitySet<PersonCategory>.

Всякий раз, когда в эти поля вносятся изменения, обновляются также связанные объекты:

  • Если я изменю свойство Person на PersonCategory на ноль, код также обновит соответствующий EntitySet<PersonCategory>, соответственно удалив это PersonCategory из EntitySet<PersonCategory>

    * предыдущего человека 1044 *
  • Если я добавлю новый PersonCategory к EntitySet<PersonCategory> человека, код автоматически установит свойство Person для нового родителя Person.

Так что да, основной ответ - LINQ to SQL достаточно умен, чтобы справиться с этим для вас - до тех пор, пока вы генерируете код модели из своей базы данных.

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