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

时间:2012-01-31 17:04:08

标签: c# winforms entity-framework

我在SQL中有2个表。一个叫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 Participants中。

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

 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 个答案:

答案 0 :(得分:1)

我用2个解决方案解决了这个问题。

  1. 我已经在课堂上声明了private EntityBazaCRM context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM);,并且一直重复使用它而不将其放入using。由于这个动作,我没有在保存或任何东西之前附加任何东西。我只是使用相同的上下文并使用currentUczestnik.Szkolenie = szkolenie;和currentUczestnik.Konsultanci = consultants;附加了我想要的任何外键。它保存没有问题。

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

    context.Attach(szkolenie);
    context.Szkolenies.Attach(szkolenie);
    currentUczestnik.SzkolenieReference.EntityKey = szkolenie.EntityKey;
    currentUczestnik.SzkolenieID = szkolenie.SzkolenieID;
    
  3. 解决方案编号3是基于旧对象创建新对象。引用的Konsultanci和Szkolenia有点重新同步(我认为它实际上是从db中重新获得它们)。

     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();
                    }
                }
            }