6

Сценарий: У меня есть объект-клиент с ленивой загрузкой. Я использую это во всей программе для вызова списка клиентов для списка. Он имеет отношения к объектам Division_Customer_Rel, Division_Email_Rel и Email_Address. Все отношения имеют Lazy = true, Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true.Другой объект с тем же идентификатором уже был связан с ошибкой сеанса

Проблема: Когда я использую новый сеанс, и я пытаюсь его сохранить, он дает мне ошибку A different object with same identifier was already associated with the session. Я попытался использовать LINQ для возврата списка без использования нового сеанса, присоединив другие объекты в вызове, но я не уверен, как использовать ActiveRecordLinq <> при подключении.

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

Код, который производит ошибку

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 
       } 

Адрес электронной почты Класс

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 
    } 
} 

Отдел клиентов 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 
    } 
} 

Отдел электронной почты Rel

#region namespace imports 

using System; 
using Castle.ActiveRecord; 

#endregion 

namespace Sens 
{ 
    [Serializable, ActiveRecord("dbo.Division_Email_Rel")] 
    public class Division_Email_Rel : ActiveRecordValidationBase<Division_Email_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 = "Email_ID", Cascade = CascadeEnum.All)] 
     public Email_Address Email { get; set; } 

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

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

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

     #endregion 
    } 
} 
+0

1. Что LINQ to SQL должно здесь делать? Это совсем другая библиотека. 2. Можете ли вы опубликовать код, который выдает «Другой объект с тем же идентификатором уже был связан с сеансом»? –

+0

Вы также можете опубликовать код для классов Division_Customer_Rel, Division_Email_Rel и Email_Address? –

+0

@Mauricio Scheffer Я выложу код в понедельник (Работа) – Gage

ответ

3

Способ, которым я, наконец, получил его, чтобы сохранить после поиска по всему миру, для ответа было очистить адреса электронной почты, а не очищать их.

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

         } 

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

1

Выдворение удаляет эту специфическую ссылку «Email_Address» из кеша первого уровня NHibernate.

От клиента. EmailAddresses вы удалили весь адрес электронной почты в кеше первого уровня NHibernate.

Затем вы получаете предметы из списка писем в lst_email и добавляете их в EmailAddress для клиента как новые объекты.