Отношения между двумя объектами не могут быть определены, потому что они прикреплены к разным объектам ObjectContext. - PullRequest
0 голосов
/ 31 января 2012

У меня есть 2 таблицы в SQL. Один называется Training, а другой - Consultants. Обучение - это пара полей, таких как ID, Place, Time, Date, и оно также имеет ConsultantName, который является внешним ключом и связан с Consultants, имеющим ConsultantName, ConsultantFirstName и т. Д.

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

Training Training = context.Trainings.First(p => p.TrainingID == varTraining.TrainingID);
                context.Trainings.Attach(Training);
                currentUczestnik.Training = Training;

Вот код:

        using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM))
        {
            Training Training = context.Trainings.First(p => p.TrainingID == varTraining.TrainingID);
            foreach (var currentUczestnik in listaUczestnikow)
            {
                context.Trainings.Attach(Training);
                currentUczestnik.Training = Training;
                if (context.TrainingUczestnicies.Any(t => t.TrainingUczestnicy1 == currentUczestnik.TrainingUczestnicy1))
                {
                    context.TrainingUczestnicies.Attach(currentUczestnik);
                    context.ObjectStateManager.ChangeObjectState(currentUczestnik, EntityState.Modified);
                }
                else
                {
                    // context.Detach(currentUczestnik.Consultant);
                    context.Consultants.Attach(currentUczestnik.Consultant);
                    context.TrainingUczestnicies.AddObject(currentUczestnik);
                    //context.TrainingUczestnicies.Attach(
                }
            }
            try
            {
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                string excepion = ex.InnerException.ToString();
                MessageBox.Show(excepion);
            }

        }

Редактировать:

Полная история выглядит следующим образом.

Есть эта таблица с консультантами. Люди загружены:

using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {       
    IQueryable<Konsultanci> listaKonsultantow = from k in context.Konsultancis select k;      
    objectListViewKonsultanci.SetObjects(listaKonsultantow); 
}

Они загружаются в ObjectListview. Затем, когда пользователь нажимает на этот ObjectListView, следующие консультанты «копируются» в участников ObjectListView.

        foreach (Konsultanci konsultant in objectListViewKonsultanci.SelectedObjects) {
            dodajUczestnikowSzkolen(konsultant);
        }

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

    private void dodajUczestnikowSzkolen(Konsultanci konsultant) {
        SzkolenieUczestnicy nowyUczestnik = new SzkolenieUczestnicy();
        nowyUczestnik.Konsultanci = konsultant;

        //nowyUczestnik.SzkolenieUzytkownik = Settings.currentlyLoggedKonsultant.KonsultantNazwa;
        nowyUczestnik.SzkolenieUzytkownikData = DateTime.Now;
        //listaUczestnicy.Add(nowyUczestnik);
        objectListViewUczestnicy.AddObject(nowyUczestnik);
    }

Теперь пользователи сохраняют Обучение (некоторые поля, такие как Дата, Время, Тема были прикреплены к currentSzkolenie (Обучение):

    private void sqlZapiszSzkolenie() {

        using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {
            if (context.Szkolenies.Any(t => t.SzkolenieID == currentSzkolenie.SzkolenieID)) {
                context.Szkolenies.Attach(currentSzkolenie);
                context.ObjectStateManager.ChangeObjectState(currentSzkolenie, EntityState.Modified);
            } else {
                context.Szkolenies.AddObject(currentSzkolenie);
            }


            context.SaveChanges();
            context.Detach(currentSzkolenie);

        }
    }

Итак, после того, как я сохранил Обучение, и Обучение теперь находится в базе данных, я отправляюсь, чтобы сохранить Участников. Я беру currentSzkolenie (глобальный var для Training) и передаю его как переменную:

 private void sqlZapiszUczestnikow(ObjectListView listaUczestnikow, Szkolenie varSzkolenie) {


        foreach (SzkolenieUczestnicy currentUczestnik in listaUczestnikow.Objects) {
            using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {
                  Szkolenie szkolenie = context.Szkolenies.First(p => p.SzkolenieID == varSzkolenie.SzkolenieID);

                  context.Attach(szkolenie);
                  currentUczestnik.Szkolenie = szkolenie;
              //  currentUczestnik.Szkolenie.EntityKey = szkolenie.EntityKey;
                if (context.SzkolenieUczestnicies.Any(t => t.SzkolenieUczestnicy1 == currentUczestnik.SzkolenieUczestnicy1)) {
                    context.SzkolenieUczestnicies.Attach(currentUczestnik);
                    context.ObjectStateManager.ChangeObjectState(currentUczestnik, EntityState.Modified);
                } else {
                    // context.Detach(currentUczestnik.Konsultanci);
                    context.Konsultancis.Attach(currentUczestnik.Konsultanci);
                    context.SzkolenieUczestnicies.AddObject(currentUczestnik);

                    //context.SzkolenieUczestnicies.Attach(
                }

                try {
                    context.SaveChanges();
                } catch (Exception ex) {
                    string excepion = ex.InnerException.ToString();
                    MessageBox.Show(excepion);
                }

            }
        }
    }

А вот и все .. выдает ошибку на currentUczestnik.Szkolenie = szkolenie;

1 Ответ

1 голос
/ 01 февраля 2012

Я решил это с 2 решениями.

  1. Я объявил private EntityBazaCRM context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM); на вершине своего класса и постоянно использовал его, не помещая в using. Благодаря этому действию мне не пришлось ничего прикреплять до сохранения или чего-либо еще. Я просто использовал тот же контекст и прикрепил любые внешние ключи, которые хотел, используя currentUczestnik.Szkolenie = szkolenie; и currentUczestnik.Konsultanci = consultants ;. Сохранено без проблем.

  2. Вместо того, чтобы прикреплять весь объект, как currentUczestnik.Szkolenie = szkolenie; Я добавил его через EntityKey в SzkolenieReference и SzkolenieID.

    context.Attach(szkolenie);
    context.Szkolenies.Attach(szkolenie);
    currentUczestnik.SzkolenieReference.EntityKey = szkolenie.EntityKey;
    currentUczestnik.SzkolenieID = szkolenie.SzkolenieID;
    
  3. Решением № 3 было создание нового объекта на основе старого объекта. Упомянутые Konsultanci и Szkolenia отчасти пересинхронизированы (я думаю, что на самом деле они берут их из базы данных).

     using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {
                    if (currentUczestnik.SzkolenieUczestnicyID == 0) {
                        var nowy = new SzkolenieUczestnicy {
                            Konsultanci = context.Konsultancis.First(p => p.KonsultantNazwa == currentUczestnik.Konsultanci.KonsultantNazwa),
                            Szkolenie = context.Szkolenies.First(p => p.SzkolenieID == varSzkolenie.SzkolenieID),
                            SzkolenieUzytkownik = currentUczestnik.SzkolenieUzytkownik,
                            SzkolenieUzytkownikData = currentUczestnik.SzkolenieUzytkownikData,
                            UczestnikPotwierdzilUdzial = currentUczestnik.UczestnikPotwierdzilUdzial,
                            UczestnikPrzybyl = currentUczestnik.UczestnikPrzybyl
                        };
    
    
                        context.SzkolenieUczestnicies.AddObject(nowy);
                        context.SaveChanges();
                        listaDoPodmiany.Add(nowy);
    
  4. Решение № 4 - то, чем я в конечном итоге воспользовался. По сути, он обнуляет любые ссылочные объекты (сначала временно сохраняет их в объектах), а затем использует только их значения ID перед сохранением. Затем после сохранения объекты снова присоединяются.

            foreach (SzkolenieUczestnicy uczestnik in listaUczestnikow.Objects) {
                using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {
                    if (uczestnik.SzkolenieUczestnicyID == 0) { // add new object
                        var konsultant = uczestnik.Konsultanci; 
                        uczestnik.Konsultanci = null; // null attached object and reuse it's ID later on for SAVE purposes
                        uczestnik.KonsultantNazwa = konsultant.KonsultantNazwa;
                        uczestnik.Szkolenie = null; // null attached object and reuse it's ID later on for SAVE purposes
                        uczestnik.SzkolenieID = szkolenie.SzkolenieID;                       
                        context.SzkolenieUczestnicies.AddObject(uczestnik);
                        context.SaveChanges();
                        context.Detach(uczestnik); // detatch to prevent Context problems
                        uczestnik.Szkolenie = szkolenie;// reassign for use in ObjectListView
                        uczestnik.Konsultanci = konsultant; // reassign for use in ObjectListView
                    } else { // modify exisinng object 
                        context.SzkolenieUczestnicies.Attach(uczestnik);
    
                       //context.ObjectStateManager.ChangeObjectState(uczestnik, EntityState.Modified);
                        context.SaveChanges();
                    }
                }
            }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...