无法定义这两个对象之间的关系,因为它们附加到不同的ObjectContext对象

本文关键字:对象 因为 ObjectContext 关系 两个 之间 定义 | 更新日期: 2023-09-27 18:21:57

我在SQL中有两个表。一个被称为Training,一个被称作Consultants。训练是像ID, Place, Time, Date这样的两个字段,它还有ConsultantName,它是外键,并与具有顾问名称、顾问名字等的Consultants相连。

在保存Training期间,我首先保存Training,然后将Training值传递为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);
    }

现在用户保存Training(一些字段,如Date、Time、Topic已附加到currentSzkolenie(Training):

    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(用于训练的全局变量)并将其作为变量传递:

 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; 上引发错误

无法定义这两个对象之间的关系,因为它们附加到不同的ObjectContext对象

我用两个解决方案解决了它。

  1. 我已经在类的顶部声明了private EntityBazaCRM context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM);,并一直重用它,而没有将它放入using中。多亏了这个动作,我在保存之前不必附加任何东西。我只是使用了相同的上下文,并使用currentUczestnik.Szkolenie = szkolenie;和currentUczestnik.Konsultanci=consultants;附加了我想要的任何外键;。它保存得很好。

  2. 我没有像currentUczestnik.Szkolenie = szkolenie;那样附加整个对象,而是通过SzkolenieReference和SzkorenieID上的EntityKey添加了它。

    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();
                    }
                }
            }
    
相关文章: