Вставка элемента в текстовый текст LINQ to SQL - не появляется до перезапуска приложения - PullRequest
1 голос
/ 13 февраля 2009

У меня есть приложение ASP.NET MVC (с использованием кандидата на выпуск), которое работает с библиотекой классов, которая, среди прочего, использует LINQ to SQL для сохранения данных.

Одной из вещей, которую поддерживает app / db, является концепция «Папка» - как папка на диске, но с иерархией, которая существует только в базе данных. Другие объекты базы данных находятся в этих папках, если смотреть с точки зрения пользователя.

Каждый класс в библиотеке классов имеет собственную статическую ссылку на мой объект DataContext. Кроме того, каждый контроллер MVC имеет свой собственный объект DataContext.

У меня есть два Действия, возвращающие данные JSON. Одним из них является «GetFoldersJSON», который возвращает структуру папок в формате, подходящем для списка выбора (раскрывающегося списка). Другой - «AddFolderJSON», который принимает некоторые данные формы, вставляет новую папку в базу данных, а затем возвращает GetFoldersJSON () для отправки нового списка папок клиенту. Клиент использует AJAX с этими действиями для обновления выпадающих списков после создания новой папки.

Ход этой операции таков:

  1. Действие AddFolderJSON () - получение информации формы с новым именем папки, родительской папкой и т. Д.

  2. Создать новый объект папки. Выполните dataContext.Folders.InsertOnSubmit (newFolder); Выполните dataContext.SubmitChanges (); Выполните dataContext.Refresh (OverwriteThingy, dataContext.Folders); возвращаемый результат GetFoldersJSON ()

  3. GetFoldersJSON () использует функцию, которая находится в определении папки - это частичный класс, расширяющий объект папки, отображаемый в OR. Эта функция рекурсивно добавляет папки и подпапки в плоский список, используя такой код:

    var rootFolders = from f in db.Folders
                      where f.ParentFolder == null
                      orderby f.name
                      select f;
    

db - это, конечно, локальная статическая ссылка на DataContext.

Тогда простой цикл:

    foreach (var fldr in rootFolders)
    {
        AddFolderContents(list, fldr);
    }

Функция AddFolderContents () затем добавляет текущую папку в список и продолжает вызывать себя для каждой подпапки текущей папки, создавая таким образом иерархию.

Это прекрасно работает для данных, уже находящихся в базе данных, но когда мы запускаем эту процедуру после создания новой папки, новая папка не отображается. Если мы обновим страницу, она все равно не появится. На самом деле он не отображается, пока приложение не будет перезапущено.

Я пытался делать вызовы Refresh () практически везде, и, похоже, в этом случае он не действует.

Есть ли способ сказать LINQ to SQL: «Эй, я знаю, о чем ты думаешь, но брось все и просто получи все данные из базы данных, сейчас!»?

У меня есть ноющее чувство, я слышал об этом раньше, но не смог найти его описанным здесь.

Ответы [ 3 ]

4 голосов
/ 13 февраля 2009

У меня такое ощущение, что вы не используете объект DataContext (содержащий статические ссылки) в том виде, в котором он предназначен для использования.

Объекты DataContext предназначены для использования в качестве «единицы работы» ... Создайте ее, сделайте свою работу, избавьтесь от нее. Нужно сделать еще немного работы? Создай другую, сделай свою работу, избавься от нее.

На этой странице MSDN , Microsoft говорит:

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

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

Точно так же, если вы прочтете нижнюю часть страницы 10 мифов о LINQ Джозефа и Бена Албахари (они являются авторами C # In A Nutshell ), вы увидите эту цитату об использовании статический дата-текст:

Эта стратегия приведет к устареванию данных, поскольку объекты, отслеживаемые экземпляром DataContext, не обновляются просто путем запроса.

Использование одного статического экземпляра DataContext на среднем уровне распределенного приложения вызовет дополнительные проблемы, поскольку экземпляры DataContext не являются поточно-ориентированными.

Правильный подход заключается в создании новых объектов DataContext по мере необходимости, сохраняя экземпляры DataContext достаточно недолговечными.

2 голосов
/ 13 февраля 2009

Есть ли способ сказать LINQ to SQL: «Эй, я знаю, о чем ты думаешь, но брось все и просто получи все данные из базы данных, СЕЙЧАС!»?

db = new customDataContext ();

db - это, конечно, локальная, статическая ссылка DataContext

Да, смотри туда. ASP.NET является многопоточным, и вы не хотите предоставлять общий доступ к небезопасному для работы с потоками экземпляру DataContext.


Кажется, что вы получаете доступ к папкам детей через их родителей. DataContext кэширует состояние объектов, которые он уже прочитал, и возвращает те же экземпляры вам при дальнейших запросах. Родительский экземпляр должен быть уведомлен о том, что у него есть новый дочерний экземпляр. Проверьте созданное свойство ParentFolder и посмотрите, уведомляет ли оно родительскую папку. Если это так, вы в бизнесе:

child.ParentFolder = parent;

Если нет, вам нужно сделать это следующим образом:

parent.Children.Add(child);

Не делайте это по id, автоматически сгенерированный код не уведомляет родительский объект в этом случае.

child.ParentFolderId = parent.Id; //bad, broken, do not do

Сделайте это до звонка SubmitChanges.

1 голос
/ 13 февраля 2009

Мой первый инстинкт был: -

Дэвид Б дал вам одну из возможностей, новичок в DataContect, но есть и другой.

db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, myObjectsCollection)

myObjectionCollection - это коллекция всех объектов Linq, которые вы хотите обновить из базы данных. (т. е. в большинстве случаев в вашем случае).

Осторожно, это sllllooooowwwww! Видимо в EF лучше - см. здесь .

Однако при более внимательном перечитывании я не уверен, что происходит. Linq должен найти новые записи (но не обновленные записи), и они должны появляться даже без обновления.

Хммм ....

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