Arhn - архитектура программирования

Как отправить изменения в несколько таблиц, связанных в LinqToSql?

Я делаю приложение для Windows Phone 7.1, и у меня возникают проблемы с отправкой изменений в мою базу данных. Вот структура таблиц в моей базе данных:

День ‹-1-----*-> Тренировка ‹-много-----1-> Спорт

Таким образом, в один день может быть много тренировок, а в тренировке — один вид спорта. Один и тот же вид спорта, естественно, может включать множество различных тренировок.

Первичные ключи выглядят следующим образом: Day — DateTime TrainingSession — int (генерируется БД) Sport — nvarchar(200)

Спорт будет просто иметь атрибуты sportName и iconFileName.

Я настроил ассоциации, поместив EntitySet в Day и Sport, а TrainingSession имеет EntityRef и EntityRef. Я не уверен на 100%, нужен ли EntitySet для Sport, поэтому, пожалуйста, поправьте меня, если я ошибаюсь. На данный момент я просто жестко закодировал некоторые виды спорта в своем классе Sport для тестирования, и вы увидите, как я извлекаю ObservableCollection, чтобы получить их.

Вот как я пытаюсь создать набор дней с тренировками, каждая из которых посвящена разным видам спорта:

    public void CreateDay(DateTime date)
    {
        FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString);
        DateTime firstDate = new DateTime(date.Year, date.Month, 1);

        DayItem dayItem = new DayItem();
        dayItem.DateTime = firstDate;

        fillTestDayItemWithRandomData(dayItem);

        calendarDatabase.DayItems.InsertOnSubmit(dayItem);
        calendarDatabase.SubmitChanges();
    }

    private void fillTestDayItemWithRandomData(DayItem dayItem)
    {
        ObservableCollection<SportArt> sportArtCollection = SportArtController.GetAllSports();

        dayItem.TrainingSessions = new EntitySet<TrainingSession>();
        ObservableCollection<TrainingSession> trainingSessionCollection = new ObservableCollection<TrainingSession>();

        TrainingSession trainingSession1 = new TrainingSession();
        trainingSession1.DayItem = dayItem;
        trainingSession1.SportArt = sportArtCollection[1];
        trainingSessionCollection.Add(trainingSession1);

        TrainingSession trainingSession2 = new TrainingSession();
        trainingSession2.DayItem = dayItem;
        trainingSession2.SportArt = sportArtCollection[2];
        trainingSessionCollection.Add(trainingSession2);

        FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString);
        calendarDatabase.TrainingSessions.InsertAllOnSubmit<TrainingSession>(trainingSessionCollection);
    }

Этот код не работает для меня, и он дает мне следующую ошибку:

NotSupportedException было необработанным: была предпринята попытка присоединить или добавить сущность, которая не является новой, возможно, загруженной из другого DataContext. Это не поддерживается.

До того, как я получил эту ошибку, я также получал NullReferenceExceptions.

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

Кроме того, я думал, что NullReferenceException может быть связано с тем, что я не сохраняю какие-либо виды спорта в базе данных, может ли это быть так?


Ответы:


1

Так что я много возился с этим, и сегодня я, наконец, нашел решение, которое искал.

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

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

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

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

(Я изменил DateTime дня на дату, указанную в качестве параметра метода)

public void CreateDay(DateTime date)
{
    DayItem dayItem = new DayItem();
    dayItem.DateTime = date;

        using (FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString))
        {
            calendarDatabase.DayItems.InsertOnSubmit(dayItem);
            calendarDatabase.SubmitChanges();                 
        }

    fillTestDayItemWithRandomData(dayItem);
}

Затем изменения в методе, заполняющем день тренировками, выглядят следующим образом:

-Я открываю оператор using, в котором я создаю новый контекст данных. Затем я обращаюсь к базе данных, чтобы получить список всех видов спорта, а также день, который мне нужно обновить. Я нахожу день, который мне нужно обновить, по параметру dayItemParameter. (Помните, что при извлечении из базы данных вы получите коллекцию.)

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

-Я удалил экземпляр EntitySet, потому что понял, что уже создаю его в конструкторе класса DayItem.

- Наконец, я добавляю все новые сеансы обучения в коллекцию и сразу сохраняю их все в базу данных с помощью InsertAllOnSubmit(коллекция).

private void fillTestDayItemWithRandomData(DayItem dayItemParameter)
{
        using (FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString))
        {
            ObservableCollection<SportArt> sportArtCollection;          
            var sportArts = (from SportArt sportArt in calendarDatabase.SportArts
                                 select sportArt);
            sportArtCollection = new ObservableCollection<SportArt>(sportArts);

            ObservableCollection<DayItem> dayItemCollection;
            var dayItems = (from DayItem dayItem in calendarDatabase.DayItems
                            where dayItem.DateTime == dayItemParameter.DateTime
                            select dayItem);
            dayItemCollection = new ObservableCollection<DayItem>(dayItems);

            DayItem foundDayItem = dayItemCollection[0];

            ObservableCollection<TrainingSession> trainingSessionCollection = new ObservableCollection<TrainingSession>();

            TrainingSession trainingSession1 = new TrainingSession();
            trainingSession1.DayItem = foundDayItem;
            trainingSession1.SportArt = sportArtCollection[1];
            trainingSessionCollection.Add(trainingSession1);

            TrainingSession trainingSession2 = new TrainingSession();
            trainingSession2.DayItem = foundDayItem;
            trainingSession2.SportArt = sportArtCollection[2];
            trainingSessionCollection.Add(trainingSession2);


            calendarDatabase.TrainingSessions.InsertAllOnSubmit<TrainingSession>(trainingSessionCollection);
            calendarDatabase.SubmitChanges();
        }
}

Вывод:

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

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

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

21.03.2012
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..