ऐसा लगता है कि NHibernate ADO.NET डेटाबेस कनेक्शन को पूल नहीं करता है। कनेक्शन केवल तभी बंद होते हैं जब लेनदेन किया जाता है या वापस लुढ़का जाता है। स्रोत कोड की एक समीक्षा से पता चलता है कि एनएचबीर्नेट को कॉन्फ़िगर करने का कोई तरीका नहीं है ताकि ISession का निपटारा होने पर कनेक्शन बंद हो जाए।एनएचबेर्नेट और एडीओ.NET कनेक्शन पूलिंग
इस व्यवहार का उद्देश्य क्या था? ADO.NET में कनेक्शन पूलिंग है। लेनदेन के भीतर हर समय उन्हें खोलने की जरूरत नहीं है। इस व्यवहार के साथ भी अनचाहे वितरित लेनदेन बनाए गए हैं। http://davybrion.com/blog/2010/05/avoiding-leaking-connections-with-nhibernate-and-transactionscope/ में वर्णित एक संभावित कार्यवाही इसलिए काम नहीं करती है (कम से कम NHibernate 3.1.0 के साथ नहीं)। मैं इनफॉर्मिक्स का उपयोग कर रहा हूँ। एक ही समस्या हर दूसरे डेटाबेस (NHibernate Connection Pooling) के लिए exisit लगता है।
क्या इस समस्या से परहेज कोई अन्य कामकाज या सलाह है?
यहाँ समस्या उत्पन्न होने एक इकाई परीक्षण है:
[Test]
public void DoesNotCloseConnection()
{
using (SessionFactoryCache sessionFactoryCache = new SessionFactoryCache())
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TimeSpan.FromMinutes(10) }))
{
fixture.Setup(); // Creates test data
System.Data.IDbConnection connectionOne;
System.Data.IDbConnection connectionTwo;
using (ISessionFactory sessionFactory = sessionFactoryCache.CreateFactory(GetType(), new TestNHibernateConfigurator()))
{
using (ISession session = sessionFactory.OpenSession())
{
var result = session.QueryOver<Library>().List<Library>();
connectionOne = session.Connection;
}
}
// At this point the first IDbConnection used internally by NHibernate should be closed
using (ISessionFactory sessionFactory = sessionFactoryCache.CreateFactory(GetType(), new TestNHibernateConfigurator()))
{
using (ISession session = sessionFactory.OpenSession())
{
var result = session.QueryOver<Library>().List<Library>();
connectionTwo = session.Connection;
}
}
// At this point the second IDbConnection used internally by NHibernate should be closed
// Now two connections are open because the transaction is still running
Assert.That(connectionOne.State, Is.EqualTo(System.Data.ConnectionState.Closed)); // Fails because State is still 'Open'
Assert.That(connectionTwo.State, Is.EqualTo(System.Data.ConnectionState.Closed)); // Fails because State is still 'Open'
}
}
}
NHibernate-सत्र के निपटान कुछ नहीं करता है के बाद से हम एक सौदे में अभी भी
SessionImpl.cs:
public void Dispose()
{
using (new SessionIdLoggingContext(SessionId))
{
log.Debug(string.Format("[session-id={0}] running ISession.Dispose()", SessionId));
if (TransactionContext!=null)
{
TransactionContext.ShouldCloseSessionOnDistributedTransactionCompleted = true;
return;
}
Dispose(true);
}
}
कस्टम कनेक्शन प्रदाता को इंजेक्शन करना भी काम नहीं करेगा क्योंकि कनेक्शन प्रबंधक को कनेक्शन प्रबंधक को कॉल करने के लिए कई पूर्व शर्तएं हैं जो जांच कर रही हैं कि कनेक्शन को बंद करना लेनदेन की अनुमति नहीं है।
ConnectionManager.cs:
public IDbConnection Disconnect() {
if (IsInActiveTransaction)
throw new InvalidOperationException("Disconnect cannot be called while a transaction is in progress.");
try
{
if (!ownConnection)
{
return DisconnectSuppliedConnection();
}
else
{
DisconnectOwnConnection();
ownConnection = false;
return null;
}
}
finally
{
// Ensure that AfterTransactionCompletion gets called since
// it takes care of the locks and cache.
if (!IsInActiveTransaction)
{
// We don't know the state of the transaction
session.AfterTransactionCompletion(false, null);
}
}
}
जहाँ तक मुझे पता है, डेटाबेस लेन-देन का उपयोग करने में एक ही कनेक्शन की जरूरत है। तो मुझे यह अजीब नहीं लगता है कि जब तक लेनदेन चल रहा है तब तक यह एक कनेक्शन जीवित रहता है? यदि कनेक्शन पूल में वापस कर दिया गया है, तो ऐसा कुछ भी नहीं है जो सुनिश्चित करता है कि आपको दूसरी बार पूल से एक ही कनेक्शन प्राप्त होगा। – jishi
हालांकि, आपके ठोस परीक्षण में, आप अंतर्निहित आईडीबीकनेक्शन की जांच कर रहे हैं, जो मुझे लगता है कि एडीओ.NET का हिस्सा है, और क्या यह एडीओ.NET कनेक्शन पूलिंग नहीं है जिसे आप उस मामले में परीक्षण कर रहे हैं? आपको क्या करना चाहिए दो अलग-अलग सत्र (उसी फैक्ट्री से भी, सुनिश्चित करें कि यह मामला है) और सुनिश्चित करें कि आपको एक ही कनेक्शन प्राप्त हो। – jishi
प्रत्येक लेनदेन की शुरुआत में चालक वर्ग (मेरे मामले में OdbcDriver) एक नया डीबीकनेक्शन (ओडीबीसी कनेक्शन) बनाता है। यह कनेक्शन पूरे लेनदेन को खोलता है जो अनावश्यक है। मैंने जो परीक्षण लिखा है वह वास्तव में एक सत्र फैक्ट्री से दो अलग-अलग सत्रों का उपयोग करता है। – Antineutrino