2010-05-20 14 views
5

पर कास्ट त्रुटि मेरी साइट एंटरप्राइज़ लाइब्रेरी v 5.0 का उपयोग कर रही है। मुख्य रूप से डीएएबी। Executescalar, execedataset जैसे कुछ फ़ंक्शन अपेक्षित काम कर रहे हैं। समस्याओं दिखाई देते हैं जब मैं पाठकोंSQLDataReader

मैं इस समारोह मेरी कक्षा में शामिल हैं में है का उपयोग शुरू:

Public Function AssignedDepartmentDetail(ByVal Did As Integer) As SqlDataReader 
    Dim reader As SqlDataReader 
    Dim Command As SqlCommand = db.GetSqlStringCommand("select seomthing from somewhere where something = @did") 
    db.AddInParameter(Command, "@did", Data.DbType.Int32, Did) 
    reader = db.ExecuteReader(Command) 
    reader.Read() 
    Return reader 
End Function 

यह बहुत तरह मेरे aspx.vb से कहा जाता है:

reader = includes.AssignedDepartmentDetail(Did) 
If reader.HasRows Then 
    TheModule = reader("templatefilename") 
    PageID = reader("id") 
Else 
    TheModule = "#" 
End If 

इससे

प्रकार 'Microsoft.Practices.EnterpriseLibrary.Data.RefCountingDataReader' की वस्तु कास्ट करने के लिए टाइप करने में असमर्थ 'Sys: db.ExecuteReader लाइन पर निम्न त्रुटि tem.Data.SqlClient.SqlDataReader '।

क्या कोई इस काम को प्राप्त करने के बारे में कोई प्रकाश डाल सकता है। Entlib के माध्यम से पाठकों से निपटने के दौरान मैं हमेशा समस्याओं में भाग लेगा?

उत्तर

0

मुझे लगता है कि मेरे पास एक समाधान समाधान है।

enter code here 

    ' Create the Database object, using the default database service. The 
    ' default database service is determined through configuration. 
    Dim db As Microsoft.Practices.EnterpriseLibrary.Data.Database = EnterpriseLibraryContainer.Current.GetInstance(Of Microsoft.Practices.EnterpriseLibrary.Data.Database)(DatabaseName) 

    Dim dbCommand As DbCommand 
    dbCommand = db.GetStoredProcCommand(StoredProcedureName) 

    'create a new database connection based on the enterprise library database connection 
    Dim dbConnection As System.Data.Common.DbConnection 
    dbConnection = db.CreateConnection 
    dbConnection.Open() 

    'set the dbCommand equal to the open dbConnection 
    dbCommand.Connection = dbConnection 

    'return a ADO sqlDatareader but still managed by the EnterpriseLibrary 
    Return dbCommand.ExecuteReader(CommandBehavior.CloseConnection) 
+0

यह अनचाहे IDataReader को वापस कर देगा, जिसे आवश्यक होने पर प्रदाता विशिष्ट पाठक को डाला जा सकता है, जैसे SqlDataReader। आप सही हैं कि यह RefCountingDataReader नहीं है और ओपी की कास्टिंग त्रुटि का सामना नहीं करेगा। हालांकि, RefCountingDataReader कार्यान्वयन के मुख्य कारणों में से एक को इंगित करना महत्वपूर्ण है ... (अगली टिप्पणी देखें) ... – mdisibio

+0

यदि कोई सिस्टम है। उपयोग में लेनदेन (उदाहरण के लिए ट्रांज़ेक्शनस्कोप() में लिपटे डेटाबेस कॉल) यह एक दूसरे लेनदेन के रूप में "dbConnection.Open()" देखेंगे, चाहे आप वास्तव में कुछ भी संशोधित कर रहे हों या नहीं। और दूसरे कनेक्शन के साथ, यह लेनदेन के प्रबंधन के लिए एमएस वितरित लेनदेन समन्वयक संलग्न करेगा। यह एक कोने का मामला है, लेकिन यदि ऐसा होता है, तो यह कुछ डेटा लाने के लिए एक जबरदस्त ओवरहेड होगा (और डीटीसी सेवा आपके सर्वर पर भी नहीं चल रही है)। – mdisibio

1

एंटरप्राइज़ लाइब्रेरी में ExecuteReader IDCataReader को RefCountingDataReader में लपेटता है कि SqlDataReader IDataReader इंटरफ़ेस लागू करता है।

RefCountingDataReader में InnerReader प्रॉपर्टी है जिसे आप SqlDataReader पर डाल सकते हैं। नीचे दिया गया नमूना सी # में है लेकिन आप इसे आसानी से VB.NET में परिवर्तित कर सकते हैं।

SqlDataReader reader; 
reader = ((RefCountingDataReader)db.ExecuteReader(command)).InnerReader as SqlDataReader; 
if (reader != null) 
    reader.Read(); 
return reader; 

आशा है कि यह मदद करता है

+3

यह मत करो! यह डेटाबेस कनेक्शन रिसाव होगा! –

3

मैं इस कार्यान्वयन के साथ सावधान रहना होगा। वहाँ उद्यम लाइब्रेरी codeplex साइट पर एक धागा है कि इस के लिए backgound बताते है: क्योंकि तब उद्यम पुस्तकालय द्वारा कनेक्शन ट्रैकिंग बंद फेंक दिया जाता है, http://entlib.codeplex.com/Thread/View.aspx?ThreadId=212973

क्रिस Tavares बताते हैं कि यह सिर्फ .InnerReader वापस जाने के लिए अच्छा नहीं है (20 मई, 5:39 अपराह्न से उनकी प्रतिक्रिया): "वह दृष्टिकोण पूरी तरह से आपके कनेक्शन प्रबंधन को खराब कर देगा। रैपर के लिए पूरा कारण यह है कि हम निपटान समय पर सामान को साफ करने के लिए अतिरिक्त कोड निष्पादित कर सकते हैं। आंतरिक पाठक को पकड़ना और बाहरी विलुप्त कनेक्शन को फेंकना! "

तो हाँ, यह एक दर्द का सामना करने के लिए थोड़ा सा दर्द है, हम एक ही situa में हैं tion।

सादर, माइक

1

मैं लीक कनेक्शन हो रहा है क्योंकि मेरे सारे डीए तरीकों एक SqlDataReader की आवश्यकता है। अब मुझे आंतरिक RefCountingDataReader वापस करना होगा और बाहरी पाठक को कभी भी बंद नहीं कर सकता। पुरानी एंटरप्राइज़ लाइब्रेरी एक SqlDataReader लौटने के साथ ठीक काम कर रही थी।

+0

असल में, पुरानी एंटलिब ठीक काम नहीं कर रही थी, इसलिए हमने बदलाव किया। समस्या सूक्ष्म थी, लेकिन परिणामस्वरूप कुछ बहुत बुरा, ट्रांज़ेक्शनस्कोप का उपयोग करते समय बहु-थ्रेडेड अनुप्रयोगों में अपवादों को ट्रैक करना मुश्किल था। –

+0

बस स्पष्ट होने के लिए, InnerReader SqlDataReader है और 'बाहरी' पाठक RefCountingDataReader है ... – mdisibio

0

आप इंटरफ़ेस, नहीं ठोस वर्ग का उपयोग करना चाहिए।

Public Function AssignedDepartmentDetail(ByVal Did As Integer) As IDataReader 
    Dim reader As IDataReader 
    Dim Command As SqlCommand = db.GetSqlStringCommand("select seomthing from somewhere where something = @did") 
    db.AddInParameter(Command, "@did", Data.DbType.Int32, Did) 
    reader = db.ExecuteReader(Command) 
    reader.Read() 
    Return reader 
End Function 

और उपयोग। व्यक्तिगत रूप से, मैं प्रेजेंटेशन लेयर पेज में कभी भी डेटरेडर का उपयोग नहीं करता, लेकिन प्रत्येक के लिए मुझे लगता है।

Private Const TemplateFileName_Select_Column_Ordinal As Integer = 0 
Private Const Id_Select_Column_Ordinal As Integer = 1 

Private Sub DoSomething() 
dim reader as IDataReader 
reader = includes.AssignedDepartmentDetail(Did) 
If reader.HasRows Then 
    TheModule = reader(TemplateFileName_Select_Column_Ordinal) 
    PageID = reader(Id_Select_Column_Ordinal) 
Else 
    TheModule = "#" 

    reader.Close() ''Dude, close your reader(s) 

End If 
+0

इंटरफ़ेस का उपयोग करना सबसे अच्छा अभ्यास और सबसे प्रदाता अज्ञात तरीका है, लेकिन कभी-कभी आपको प्रदाता विशिष्ट वर्ग की अतिरिक्त विशेषताओं की आवश्यकता होती है। स्टीफन का जवाब दर्शाता है कि डीएएबी के अंतर्निहित कनेक्शन प्रबंधन को तोड़ने के बिना इसे कैसे किया जाए। – mdisibio

1

मैं http://entlib.codeplex.com/discussions/212973 और http://entlib.codeplex.com/discussions/211288 पर ctavars द्वारा पोस्ट की गई टिप्पणियों और कोड को ध्यान में रखा गया है, एक SQL डेटा पाठक प्राप्त करने के लिए निम्न सामान्य दृष्टिकोण में जिसके परिणामस्वरूप।

सामान्य रूप से आप उपयोग कथन में IDataReader का उपयोग करते हैं, फिर जब आप कर सकते हैं तो सीधे उस संदर्भ का उपयोग करें। जब आपको कुछ SQL- विशिष्ट की आवश्यकता होती है तो उस पर AsSqlDataReader पर कॉल करें।

इस विस्तार के वर्ग कहीं जोड़ें:

/// <summary> 
/// Obtains an <see cref="SqlDataReader"/> from less derived data readers in Enterprise Library 
/// </summary> 
/// <remarks> 
/// See http://entlib.codeplex.com/discussions/212973 and http://entlib.codeplex.com/discussions/211288 
/// for a discussion of why this is necessary 
/// </remarks> 
public static class SqlDataReaderExtension 
{ 
    /// <summary> 
    /// Allows the internal <see cref="SqlDataReader"/> of a <see cref="RefCountingDataReader"/> to be accessed safely 
    /// </summary> 
    /// <remarks> 
    /// To ensure correct use, the returned reference must not be retained and used outside the scope of the input 
    /// reference. This is so that the reference counting does not get broken. In practice this means calling this method 
    /// on the base reader every time a reference to it is required. 
    /// </remarks> 
    public static SqlDataReader AsSqlDataReader(this RefCountingDataReader reader) 
    { 
     return (SqlDataReader)(reader.InnerReader); 
    } 

    /// <summary> 
    /// Allows the internal <see cref="SqlDataReader"/> of a <see cref="IDataReader"/> to be accessed safely 
    /// </summary> 
    /// <remarks> 
    /// To ensure correct use, the returned reference must not be retained and used outside the scope of the input 
    /// reference. This is so that the reference counting does not get broken. In practice this means calling this method 
    /// on the base reader every time a reference to it is required. 
    /// </remarks> 
    public static SqlDataReader AsSqlDataReader(this IDataReader reader) 
    { 
     return (SqlDataReader)(((RefCountingDataReader)(reader)).InnerReader); 
    } 
} 

... तो एक SQLReader साथ डेटा को पढ़ने के लिए, कुछ इस तरह करते हैं:

using (IDataReader reader = db.ExecuteReader(command)) 
{ 
    while (reader.Read()) 
    { 
     reader.GetInt32(reader.GetOrdinal("SomeColumn")), 
     reader.GetInt32(reader.GetOrdinal("SomeOtherColumn")), 
     reader.GetInt32(reader.GetOrdinal("SomeFurtherColumn")), 
     // Obtain the SQL data reader each time it is used 
     // (Note that GetDateTimeOffset is not on the standard IDataReader) 
     reader.AsSqlDataReader().GetDateTimeOffset(reader.GetOrdinal("SQLSpecificColumn")) 
     reader.AsSqlDataReader().GetDateTimeOffset(reader.GetOrdinal("AnotherSQLSpecificColumn")) 
     reader.GetString(reader.GetOrdinal("SomeAdditionalColumn")) 
    } 
} 
+1

स्रोत कोड में कई घंटे खर्च करने के बाद, मेरा मानना ​​है कि यह वास्तव में सही दृष्टिकोण है। यह जोर दिया जाना चाहिए कि ऊपर दिए गए स्वीकृत उत्तर मेमोरी लीक की अनुमति देंगे यदि कोई सिस्टम। ट्रांज़ेक्शन (ट्रांजैक्शनस्कोप) का उपयोग किया जाता है। – mdisibio

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