2011-01-31 21 views
7

मुझे एक स्पोरैडिक त्रुटि मिल रही है जो पुन: पेश करना मुश्किल है। मेरा पहला अनुमान यह है कि किसी भी तरह मेरे पास एक लीकिंग निबर्ननेट सत्र है, हालांकि जब मैं nhibernate profiler चलाता था, तो मुझे सामान्य से बहुत कुछ नहीं दिखाई देता था।NHibernate: System.Argument अपवाद: एक ही कुंजी वाला एक आइटम पहले ही जोड़ा जा चुका है

  • MVC 2.0
  • Fluent संस्करण 1.1.0.685
  • NHibernate संस्करण 2.1.2.4000

अपवाद: System.ArgumentException: एक ही कुंजी के साथ एक आइटम पहले से ही जोड़ दिया गया है ।

स्टैक ट्रेस: ​​ System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add) at NHibernate.Util.ThreadSafeDictionary 2.Add (TKey कुंजी, TValue मूल्य) NHibernate.SqlTypes.SqlTypeFactory.GetTypeWithLen [टी] (Int32 लंबाई, TypeWithLenCreateDelegate createDelegate) पर पर पर NHibernate.Type.EnumStringType..ctor (प्रकार enumClass, Int32 लंबाई)

मैं एक रिपोजिटरी मॉडल का उपयोग कर रहा हूँ। यहां मेरी रिपोजिटरी क्लास है।

public sealed class Repository<T> : IRepository<T> where T : CoreObjectBase 
{ 
    #region IRepository<T> Members 

    private ISession Session 
    { 
     get 
     { 
      return new SessionHelper().GetSession(); 
     } 
    } 

    public IQueryable<T> GetAll() 
    { 
     return (from entity in Session.Linq<T>() select entity); 
    } 

    public T GetById(int id) 
    { 
     return Session.Get<T>(id); 
    } 

    public void Save(params T[] entities) 
    { 
     using (ITransaction tx = Session.BeginTransaction()) 
     { 
      for (int x = 0; x < entities.Count(); x++) 
      { 
       var entity = entities[x]; 

       entity.Validate(); 

       Session.SaveOrUpdate(entities[x]); 

       if (x == entities.Count() - 1 || (x != 0 && x % 20 == 0)) //20 is the batch size 
       { 
        Session.Flush(); 
        Session.Clear(); 
       } 
      } 
      tx.Commit(); 
     } 
    } 

    public void SaveWithDependence<K>(T entity, K dependant) where K : CoreObjectBase 
    { 
     entity.Validate(); 
     dependant.Validate(); 

     using (ITransaction tx = Session.BeginTransaction()) 
     { 
      Session.SaveOrUpdate(entity); 
      Session.SaveOrUpdate(dependant); 
      tx.Commit(); 
     } 
    } 

    public void Save(T entity) 
    { 
     entity.Validate(); 

     using (ITransaction tx = Session.BeginTransaction()) 
     { 
      Session.SaveOrUpdate(entity); 
      tx.Commit(); 
     } 
    } 

    public void Delete(T entity) 
    { 
     using (ITransaction tx = Session.BeginTransaction()) 
     { 
      Session.Delete(entity); 
      tx.Commit(); 
     } 
    } 

    public T GetOne(QueryBase<T> query) 
    { 
     var result = query.SatisfyingElementFrom(Session.Linq<T>()); 

     return result; 

     //return query.SatisfyingElementFrom(Session.Linq<T>()); 
    } 

    public IQueryable<T> GetList(QueryBase<T> query) 
    { 
     return query.SatisfyingElementsFrom(Session.Linq<T>()); 
    } 

    /// <summary> 
    /// remove the sepcific object from level 1 cache so it can be refreshed from the database 
    /// </summary> 
    /// <param name="entity"></param> 
    public void Evict(T entity) 
    { 
     Session.Evict(entity); 
    } 
    #endregion 
} 

और यहाँ मेरी सत्र सहायक, this से अनुकूलित है।

public sealed class SessionHelper 
{ 
    private static ISessionFactory _sessionFactory; 
    private static ISession _currentSession; 

    public ISession GetSession() 
    { 
     ISessionFactory factory = getSessionFactory(); 
     ISession session = getExistingOrNewSession(factory); 
     return session; 
    } 

    private ISessionFactory getSessionFactory() 
    { 
     if (_sessionFactory == null) 
     { 
      _sessionFactory = BuildSessionFactory(); 
     } 

     return _sessionFactory; 
    } 

    private ISessionFactory BuildSessionFactory() 
    { 
     return Fluently.Configure().Database(
      FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005 
       .ConnectionString(c => c 
        .FromConnectionStringWithKey("MyDatabase")) 
        .AdoNetBatchSize(20)) 
       .Mappings(m => m.FluentMappings.AddFromAssemblyOf<SessionHelper>()) 
       .BuildSessionFactory(); 
    } 

    private ISession getExistingOrNewSession(ISessionFactory factory) 
    { 
     if (HttpContext.Current != null) 
     { 
      ISession session = GetExistingWebSession(); 
      if (session == null) 
      { 
       session = openSessionAndAddToContext(factory); 
      } 
      else if (!session.IsOpen) 
      { 
       session = openSessionAndAddToContext(factory); 
      } 

      return session; 
     } 

     if (_currentSession == null) 
     { 
      _currentSession = factory.OpenSession(); 
     } 
     else if (!_currentSession.IsOpen) 
     { 
      _currentSession = factory.OpenSession(); 
     } 

     return _currentSession; 
    } 

    public ISession GetExistingWebSession() 
    { 
     return HttpContext.Current.Items[GetType().FullName] as ISession; 
    } 

    private ISession openSessionAndAddToContext(ISessionFactory factory) 
    { 
     ISession session = factory.OpenSession(); 
     HttpContext.Current.Items.Remove(GetType().FullName); 
     HttpContext.Current.Items.Add(GetType().FullName, session); 
     return session; 
    } 
} 

इस मुद्दे से बचने के लिए कोई विचार या सुझाव?

+0

जोश, क्या आप अपना सत्र हेल्पर थ्रेड सुरक्षित करते हैं? –

उत्तर

2

समस्या है कि SessionHelper धागा सुरक्षित नहीं है, है। यह संभावित रूप से कई सत्र कारखानों का निर्माण करेगा (यह सिंगलटन का खराब कार्यान्वयन है), जो बदले में आप जो त्रुटि देख रहे हैं उसका कारण बनता है।

मैं इसके बजाय मार्गदर्शन के रूप में SharpArchitecture का उपयोग करने की सलाह देता हूं।

+0

मैं वास्तव में अपने प्रोजेक्ट में एक और ढांचा आयात नहीं करना चाहता हूं। मेरा सेटअप ऐसा है कि मेरी वेब प्रोजेक्ट को निबर्ननेट या लाइब्रेरी रेफरेंसिंग निबर्ननेट का कोई ज्ञान नहीं है, और मैं इसे इस तरह से रखना चाहता हूं। एमवीसी ऐप -> सेवा परत -> रिपोजिटरी परत -> सत्रहेल्पर। इसे इस उद्देश्य से डिजाइन किया गया है क्योंकि एक विंडोज ऐप एक वेब सेवा से जुड़ता है जो सेवा परत का भी उपयोग करता है। – Josh

+1

@ जोश: आपको संपूर्ण ढांचा खरीदने की ज़रूरत नहीं है, आप बस कोड ब्राउज़ कर सकते हैं और इसके विचारों का उपयोग कर सकते हैं। –

+1

शार्प आर्किटेक्चर चला गया है – madth3

1

मैं एक ही मुद्दे में भाग गया, "एक ही कुंजी के साथ एक आइटम पहले से ही जोड़ दिया गया है" जबकि nhibernate विन्यास का निर्माण।

मेरे लिए क्या हो रहा था कि दो धागे प्रोग्राम के रूप में अलग अलग विन्यास, विभिन्न डेटाबेस से कनेक्ट करने के एक ही समय में इरादा निर्माण किया गया था।

मैं पूरी विन्यास निर्माता के चारों ओर एक लॉक जोड़ा था, और समस्या दूर चला गया।

तो मुझे लगता है कि कॉन्फ़िगरेशन ऑब्जेक्ट कुछ आंतरिक वैश्विक स्थिति पर निर्भर करता है, यानी मान लीजिए कि कॉन्फ़िगरेशन स्वयं एक सिंगलटन है (जैसा कि मुझे लगता है कि यह होगा, अगर यह पूरी तरह से फाइल संचालित है, प्रोग्रामेटिक रूप से निर्मित के विपरीत)।

1

मुझे लगता है कि यह एक पुराने सवाल है, लेकिन मैं एक ऐसी ही त्रुटि बस कुछ ही दिन पहले किया था, NHibernate 3.0 का उपयोग कर।

पाठकों कि इस मुद्दे पर आते हैं हो सकता है के लिए: इस NHibernate के पुराने संस्करणों में एक ज्ञात धागे की सुरक्षा की समस्या का परिणाम है। यह संस्करण 3.2 में तय किया गया था लेकिन पुराने संस्करणों में फिक्स नहीं होगा और यह समस्या उत्पन्न हो सकती है।यह बग प्रविष्टि समस्या का वर्णन करती है: https://nhibernate.jira.com/browse/NH-3271

संबंधित मुद्दे

 संबंधित मुद्दे