6

Szenario: Ich habe ein Kundenobjekt mit aktiviertem Lazy Loading. Ich verwende das im gesamten Programm, um eine Liste von Kunden für eine Listbox aufzurufen. Es hat Beziehungen zu den Objekten Division_Customer_Rel, Division_Email_Rel und Email_Address. Alle aus den Beziehungen haben Lazy = true, Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true.Ein anderes Objekt mit demselben Bezeichner war bereits mit dem Sitzungsfehler verknüpft

Problem: Wenn ich eine neue Sitzung verwende und versuche, sie zu speichern, gibt es den Fehler A different object with same identifier was already associated with the session. Ich habe versucht, LINQ zu verwenden, um die Liste ohne Verwendung einer neuen Sitzung zurückzugeben, indem ich die anderen Objekte in dem Aufruf verknüpfe, aber ich bin nicht sicher, wie ActiveRecordLinq <> bei dem Verbinden zu verwenden ist.

private Customer GetCustomer() 
    { 
     return (from x in ActiveRecordLinq.AsQueryable<Customer>() 
     where x.Customer_ID == ((Customer)lst_customers.SelectedItem).Customer_ID 
     select x).First(); 
    } 

-Code, der den Fehler

using (new SessionScope()) 
       { 
       //var sess = GetSession(); 
       //var customer = 
       // sess.CreateCriteria<Customer>("c").CreateCriteria("c.DivisionCustomer_Rels").List<Customer>(). 
       //  First(); 
       var customer = GetCustomer(); 
        /* Ensure user wishes to commit the data. */ 

        var result = 
         MessageBox.Show(
          @"You are about to submit changes to customer: " + customer.CustomerName + @"." + 
          Environment.NewLine + Environment.NewLine + 
          @"Submit Changes?", @"Submit Customer Changes", MessageBoxButtons.YesNo, 
          MessageBoxIcon.Question); 
        if (result == DialogResult.Yes) 
        { 
         customer.CustomerName = txt_custName.Text; 
         customer.NamcisNumber = Convert.ToInt32(txt_namcis.Text); 
         customer.DCA = chk_dca.Checked; 
         customer.CustomerType = (CustomerType_Code) cmb_custType.SelectedItem; 
         customer.AOR = (AOR_Code) cmbAOR.SelectedItem; 
         customer.CSRep = (CSRep_Code) cmbCSRep.SelectedItem; 
         customer.DivisionCustomer_Rels.Clear(); 
         foreach (var t in lst_SectorCust.Items) 
         { 
          customer.DivisionCustomer_Rels.Add(new Division_Customer_Rel 
                    { 
                     Customer = customer 
                     , 
                     Division = (Division_Code) t, 
                     MarkedForDeletion = false 
                    }); 
         } 
         customer.CircuitCustomer_Rels.Clear(); 
         foreach (var t in lst_Circuit.Items) 
         { 
          customer.CircuitCustomer_Rels.Add(new Circuit_Customer_Rel 
                    { 
                     Circuit = (Circuit) t, 
                     Customer = customer, 
                     MarkedForDeletion = false 
                    }); 
         } 
         customer.EmailAddresses.Clear(); 
         foreach (var t in lst_email.Items) 
         { 
          var temp = (Email_Address)t; 
          temp.Customer = customer; 
          customer.EmailAddresses.Add(temp); 

         } 
         ////Need to manage the emails this way otherwise we recieve an error because of lazy loading 
         //foreach (var temp in lst_email.Items.Cast<Email_Address>()) 
         //{ 
         // temp.Customer = customer; 
         // if (!customer.EmailAddresses.Any(s=>temp.ToString().Equals(s.ToString())) && !customer.EmailAddresses.Contains(temp)) 
         // { 
         //  customer.EmailAddresses.Add(temp); 
         // } 

         //} 

         //var text = IList<Email_Address> lst_email.Items; 
         //var tem = customer.EmailAddresses.Except(lst_email.Items); 
         //for (var i = customer.EmailAddresses.Count - 1; i >= 0;i--) 
         //{ 
         // var temp = customer.EmailAddresses[i]; 

         // for (var j = 0; j < lst_email.Items.Count; j++) 
         // { 
         //  if (temp.ToString()!=lst_email.Items[j].ToString()) 
         //  { 
         //   customer.EmailAddresses.Remove(temp); 
         //  } 
         // } 
         //} 
         customer.DivisionEmail_Rels.Clear(); 
         customer.Save(); 
         MessageBox.Show(@"Changes submitted."); 
        } 
        //SessionScope.Current 
       } 

E-Mail-Adresse der Klasse

namespace Sens 
{ 
    using System; 
    using System.Collections.Generic; 
    using Castle.ActiveRecord; 

    [Serializable, ActiveRecord("dbo.Email_Address")] 
    public class Email_Address : ActiveRecordValidationBase<Email_Address> 
    { 
     #region Constructors 

     public Email_Address() 
     { 
      DivisionEmail_Rels = new List<Division_Email_Rel>(); 
     } 

     #endregion 

     #region Properties 

     [PrimaryKey(Column = "Email_ID")] 
// ReSharper disable InconsistentNaming 
     public int Email_ID { get; private set; } 

     [BelongsTo(Column = "Customer_ID")] 
     public Customer Customer { get; set; } 

     [Property(Column = "[Email]", NotNull = true, Length = 100)] 
     public string Email { get; set; } 

     [BelongsTo(Column = "EmailType_ID")] 
     public EmailType_Code EmailType { get; set; } 

     [Property(Column = "[ReceivesSENS]", NotNull = true)] 
     public bool ReceivesSENS { get; set; } 

     [Property(Column = "[MarkedForDeletion]", NotNull = true)] 
     public bool MarkedForDeletion { get; set; } 

     #endregion 

     #region HasMany DivisionEmail_Rels 

     [HasMany(typeof(Division_Email_Rel), Lazy = false,Cascade=ManyRelationCascadeEnum.AllDeleteOrphan,Inverse=true)] 
     public IList<Division_Email_Rel> DivisionEmail_Rels { get; set; } 

     #endregion 
    } 
} 

Abteilung Kunden Rel

namespace Sens 
{ 
    using System; 
    using Castle.ActiveRecord; 

    [Serializable, ActiveRecord("dbo.Division_Customer_Rel")] 
    public class Division_Customer_Rel : ActiveRecordValidationBase<Division_Customer_Rel> 
    { 
     #region Constructors 

     #endregion 

     #region Properties 

     [PrimaryKey(Column = "Relationship_ID")] 
// ReSharper disable InconsistentNaming 
     public int Relationship_ID { get; private set; } 
// ReSharper restore InconsistentNaming 

     [BelongsTo(Column = "Customer_ID")] 
     public Customer Customer { get; set; } 

     [BelongsTo(Column = "Division_ID")] 
     public Division_Code Division { get; set; } 

     [Property(Column = "[MarkedForDeletion]", NotNull = true)] 
     public bool MarkedForDeletion { get; set; } 

     #endregion 
    } 
} 

Abteilung E-Mail-Rel

produziert
+0

1. Was muss LINQ to SQL hier tun? Es ist eine ganz andere Bibliothek. 2. Können Sie den Code posten, der "Ein anderes Objekt mit demselben Bezeichner ist bereits mit der Sitzung verknüpft" ist? –

+0

können Sie auch den Code für die Klassen Division_Customer_Rel, Division_Email_Rel und Email_Address buchen? –

+0

@Mauricio Scheffer Ich werde den Code am Montag (Arbeit bezogen) – Gage

Antwort

3

Die Art, wie ich es schließlich nach dem googeln überall für eine Antwort erhalten hatte, war, die Email_Addresses zu löschen, anstatt sie zu löschen.

SessionScope.Current.Evict(customer.EmailAddresses); 
         foreach (var t in lst_email.Items) 
         { 
          var temp = (Email_Address)t; 
          temp.Customer = customer; 
          customer.EmailAddresses.Add(temp); 

         } 

Nicht sicher, warum das funktionierte, wenn jemand erklären könnte, dass groß wäre. Ich poste dies hier, damit es hoffentlich Zeit für die nächste Person spart, die auf diesen Fehler trifft.

1

Durch das Entfernen wird diese spezifische "Email_Address" -Referenz aus dem NHibernate-Cache der ersten Ebene entfernt.

Von customer.EmailAddresses haben Sie alle E-Mail-Adressen im NHibernate-Cache der ersten Ebene entfernt.

Sie erhalten dann Artikel aus der Liste der E-Mails in lst_email und fügen sie in die EmailAddress für den Kunden als neue Objekte ein.