2009-09-24 8 views
9

मैं अपने डोमेन के साथ NHibernate में मुद्दों पर चल रहा हूं। मैं "सत्र बंद हो रहा है!" त्रुटियों। कुछ एक तो कृपया मुझे जब प्रत्येक उपयोग करने के लिए निम्न विधियों में से एक परिभाषा और सहित सही पैटर्न दिखा सकते हैं:NHHernate ISession ऑब्जेक्ट का सही तरीके से उपयोग कैसे करें - सत्र बंद है! त्रुटियां

ISession.Close() 
ISession.Dispose() 
ISession.Disconnect() 

यहाँ मेरी समस्या है। मेरे पास एक प्रक्रिया को बंद करने के लिए एक कॉलबैक सेटअप है जो प्रत्येक दो मिनट के खिलाड़ियों को पुरस्कार बैज देता है। हालांकि मैं "सत्र बंद हो रहा है!" संग्रह को जोड़ने में सक्षम नहीं होने के बारे में त्रुटियां या त्रुटियां।

public class NHibernateRepository : IRepository 
{ 
#region Fields 

private ISession _session; 
private readonly ISessionFactory _sessionFactory; 
#endregion 

#region Constructors 

public NHibernateRepository(ISessionFactory sessionFactory) 
{ 
    _sessionFactory = sessionFactory; 
} 

#endregion 

#region IRepository Implementation 

public ISession OpenSession() 
{ 
    _session = _sessionFactory.OpenSession(); 
    return _session; 
} 

public IQueryable<TModel> All<TModel>() 
{ 
    return _session.Linq<TModel>(); 
} 

public void Save<TModel>(TModel model) 
{ 
    _session.Save(model); 
} 
public void Update<TModel>(TModel model) 
{ 
    _session.Update(model); 
} 
public void Delete<TModel>(TModel model) 
{ 
    _session.Delete(model); 
} 

public ITransaction BeginTransaction() 
{ 
    return _session.BeginTransaction(); 
} 
public void Flush() 
{ 
    _session.Flush(); 
} 
#endregion 

} 

यहाँ मेरी उपयोग है:

यहाँ मेरी भंडार है। भंडार नक्शा

private Object _awardBadgesLock = new object(); //In case the callback happens again before the previous one completes 

public void AwardBadges() 
{ 

    lock (_awardBadgesLock) 
    { 
     using(session = _repository.OpenSession()) 
     { 
      foreach (var user in _repository.All<User>().ToList()) 
      { 
       var userPuzzles = _repository.All<Puzzle>().ByUser(user.Id).ToList(); 
       var userVotes = _repository.All<Vote>().Where(x => x.UserId == user.Id).ToList(); 
       var userSolutions = _repository.All<Solution>().ByUser(user.Id).ToList().Where(x => !userPuzzles.Select(y => y.Id).Contains(x.PuzzleId)); 
       var ledPuzzles = GetPuzzlesLedByUser(user.Id); 

       AwardPlayerBadge(user, userSolutions); 
       AwardCriticBadge(user, userVotes); 
       AwardCreatorBadge(user, userPuzzles); 
       AwardRidlerBadge(user, userPuzzles); 
       AwardSupporterBadge(user, userVotes); 
       AwardPopularBadge(user, userPuzzles); 
       AwardNotableBadge(user, userPuzzles); 
       AwardFamousBadge(user, userPuzzles); 
       AwardLeaderBadge(user, ledPuzzles); 

       using (var tx = _repository.BeginTransaction()) 
       { 
        _repository.Update(user); 
        tx.Commit(); 
       } 
      } 
     } 
    } 

} 
+0

क्या यह एक वेब ऐप है? – mxmissile

+0

हां मैं एक वेब ऐप हूं लेकिन मैं वेब सत्र के साथ एनएचबीर्नेट सत्र को एकीकृत नहीं कर रहा हूं। – Micah

+3

क्या _repository कहीं और इस्तेमाल किया जा रहा है?क्योंकि, एक और ओपनसेशन() कॉल पहले खो देगा। – dotjoe

उत्तर

0

मुद्दा यह तथ्य है कि ISession थ्रेड-सुरक्षित नहीं है। अलग-अलग धागे पर कई विधियों को निकाल दिया गया था, जिनमें सभी ने आईएसशन का एक उदाहरण बनाया था। मुद्दा वास्तव में इस तथ्य के साथ था कि वे सभी एक ही सत्र फैक्ट्री साझा करते थे। छवि इन तरीकों में से दोनों अलग-अलग धागे पर बंद निकाल दिया जाता है:

ISessionFactory _sessionFactory; 

void MethodOne() 
{ 
    using(ISession session = _sessionFactory.OpenSession()) 
    { 
     //Do something with really quick with the session 
     //Then dispose of it 
    } 
} 

void MethodTwo() 
{ 
    //OpenSession() actually returns the same instance used in the 
    //previous method that has already disposed of the object; 
    using(ISession session = _sessionFactory.OpenSession()) 
    { 
     //Do something with a session that has already been disposed 
     //throws errors 

    } 
} 

मैं यह मूल रूप से इन स्थितियों में NHibernate खुदाई की गई थी कैसे तय की और बजाय संग्रहीत procs बुलाया। मुझे लगता है कि यह मेरी स्थिति में वैसे भी अधिक प्रदर्शन करने वाला साबित हुआ।

+2

दिलचस्प - आप किस 'ISessionFactory' कार्यान्वयन का उपयोग कर रहे हैं? [इंटरफ़ेस का प्रलेखन] (https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/ISessionFactory.cs) कहता है "कार्यान्वयनकर्ता थ्रेडसेफ होना चाहिए।" –

+0

यह बिल्कुल समस्या है। "कार्यान्वयनकर्ता थ्रेडसेफ होना चाहिए" क्योंकि सत्र कारखाना थ्रेड-सुरक्षित नहीं है। – Micah

+5

सही, लेकिन * कौन सा * ठोस 'ISessionFactory' कार्यान्वयन? 'SessionFactoryImpl'? मुझे यकीन है कि अगर आप समस्या को पुन: उत्पन्न कर सकते हैं (या बेहतर अभी तक, बग का पता लगाएं [स्रोत कोड में] (https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Impl /SessionFactoryImpl.cs)), NHibernate टीम इसके बारे में सुनने में रुचि रखेगी। –

13

के माध्यम से इंजेक्शन प्राप्त हो रहा है आपको हमेशा सत्र का उपयोग करना चाहिए।(); बहुत अजीब आवृत्तियां

के लिए अन्य हैं
+4

मैं "उपयोग" कथन का उपयोग कर रहा हूं जो निपटान करता है। मुझे अभी भी त्रुटि मिल रही है और यह हर समय नहीं होता है। बस कुछ समय। – Micah

6

मैं सलाह जब आप सत्र के साथ समाप्त कर आप https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/ISession.cs

वैसे भी साफ करने के लिए उचित तरीके पर ISession के प्रलेखन पढ़ने के लिए यह निपटान के लिए है (या बेहतर, उपयोग कथन के उपयोग के साथ घिरा हुआ)। इस मामले में, "उपयोग" सत्र को बंद कर देता है और फाइनल को दबाता है, यानी यह सत्र ऑब्जेक्ट को अनावश्यक रूप से अगले कचरे को एकत्रित करने से बचाता है और स्मृति को बचाता है।

यदि कनेक्शन पहले ही बंद हो चुका है, तो इसका निपटान अपवाद नहीं फेंक देगा। दूसरी ओर, निपटान (या बंद होने के बाद) के बाद बंद अपवाद फेंकता है।

प्रलेखन बंद करने की बजाय डिस्कनेक्ट को कॉल करने की सिफारिश करता है, क्योंकि यह कनेक्शन पूल से कनेक्शन जारी करता है। डिस्कनेक्ट किए गए सत्र का उपयोग करने से पहले आपको रिकनेक्ट करना चाहिए।

मेरी ज़रूरतों के लिए, मैं हमेशा "उपयोग" का उपयोग करता हूं जो कॉल का निपटान करता है और कभी भी दोनों कार्यों का उपयोग नहीं करता है।

+2

लेकिन वह 'उपयोग' का उपयोग कर रहा है वह नहीं है? ... का उपयोग (सत्र = _repository.OpenSession()) – UpTheCreek

0

समस्या के बारे में, लॉकिंग की आपकी विधि तब तक सही है जब तक आप सत्र का निपटान नहीं करते हैं, लेकिन शायद बग आपके कोड के किसी अन्य भाग के नीचे है। डिजाइन के बारे में वैसे, यह बेहतर है कि आप सत्र और इस तरह कुल जड़ के लेन-देन का काम कार्यान्वयन की इकाई की वजह से खजाने को सत्र चर पारित:

using (ISession session = SessionFactory.OpenSession()) 
{ 
    Repository1 rep1 = new Repository1(session); 
    Repository2 rep1 = new Repository2(session); 
    Repository3 rep1 = new Repository3(session); 

    // some logics 

    using (var tx = session.BeginTransaction()) 
     tx.Commit(); 
} 

। । ।

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