2015-07-04 7 views
14

मैं सीख रहा हूं कि कैसे डैपर दृश्यों के पीछे काम कर रहा है।डैपर का घोंसला 'उपयोग' खंड - स्पष्टीकरण?

हालांकि मैंने निपटान के इस पैटर्न को देखा जो मुझे समझ में नहीं आया है। , कि है, क्योंकि वह करना चाहता था सशर्त के माध्यम से कनेक्शन बंद

/*1*/ public async Task<IEnumerable<T>> QueryAsync<T>(string sql, Func<IDataRecord, T> projector, DbConnection _conn, dynamic param = null) 
/*2*/ { 
/*3*/ 
/*4*/  DbDataReader reader = null; 
/*5*/  bool wasClosed = _conn.State == ConnectionState.Closed; 
/*6*/  try 
/*7*/  { 
/*8*/ 
/*9*/   using (var cmd = _conn.CreateCommand()) 
/*10*/   { 
/*11*/   if (param!=null) 
/*12*/    foreach (var prop in param.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) 
/*13*/    { 
/*14*/     var parameter = cmd.CreateParameter(); 
/*15*/     parameter.ParameterName = prop.Name; 
/*16*/     parameter.Value = prop.GetValue(param, null); 
/*17*/     cmd.Parameters.Add(parameter); 
/*18*/    } 
/*19*/ 
/*20*/    await _conn.OpenAsync().ConfigureAwait(false); 
/*21*/    cmd.CommandTimeout = 100000; 
/*22*/    cmd.CommandText = sql; 
/*23*/    reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false); 
/*24*/    List<T> buffer = new List<T>(); 
/*25*/    while (await reader.ReadAsync().ConfigureAwait(false)) buffer.Add(projector(reader)); 
/*26*/    return buffer; 
/*27*/   } 
/*28*/ 
/*29*/  } 
/*30*/  finally 
/*31*/  { 
/*32*/   using (reader) { } 
/*33*/   if (wasClosed) _conn.Close(); 
/*34*/  } 
/*35*/ } 

मैं समझ सकता क्यों वह कनेक्शन पर using का उपयोग नहीं किया: -

मोटे तौर पर सामान्य रूप मेंthis कैसे QueryAsync कार्यान्वित किया जाता है है wasClosed चर।
ऐसा करने के लिए - उसे try/finally खंड का उपयोग करना होगा। (इसलिए सशर्त समापन finally खंड में होगा)

लेकिन मेरा प्रश्न पंक्ति # 32 के बारे में है।

इसके बजाय using at the finally clause करने का है, वह कर सकता है:

using (DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) 
{ 
    List<T> buffer = new List<T>(); 
    while (await reader.ReadAsync().ConfigureAwait(false)) buffer.Add(projector(reader)); 
    return buffer; 
} 

तो finally खंड के साथ छोड़ दिया है:

finally 
{ 
    //using (reader) { } //removed 
    if (wasClosed) _conn.Close(); 
} 

प्रश्न

मैं इस using खंड देखा है आखिरकार डैपर में कई बार खंड।

मुझे यहां कुछ याद आना चाहिए, लेकिन यह पैटर्न क्या प्राप्त करता है कि मेरा सुझाव नहीं है?

+2

यह एक दोष की तरह दिखता है। आपका प्रस्ताव बेहतर है। शायद इसके लिए कोई अच्छा कारण नहीं है। – usr

उत्तर

7

मैं @MarcGravell नहीं हूं, लेकिन मुझे लगता है कि एक चीज है जो आप गायब हैं। आपके द्वारा चिपकाया गया कोड बिल्कुल आपके द्वारा संदर्भित लिंक से मेल नहीं खाता है। प्रासंगिक कोड पथ इस तरह दिखता है:

try 
{ 
    if (command.Buffered) 
    { 
     List<T> buffer = new List<T>(); 
     while (await reader.ReadAsync(cancel).ConfigureAwait(false)) 
     { 
      buffer.Add((T)func(reader)); 
     } 
     while (await reader.NextResultAsync().ConfigureAwait(false)) { } 
     command.OnCompleted(); 
     return buffer; 
    } 
    else 
    { 
     // can't use ReadAsync/cancellation; but this will have to do 
     wasClosed = false; // don't close if handing back an open reader; 
          // rely on the command-behavior. 

     var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters); 
     reader = null; // to prevent it being disposed before the caller gets to see it 
     return deferred; 
    } 
} 
finally 
{ 
    using (reader) { } // dispose if non-null 
    if (wasClosed) cnn.Close(); 
} 

विधि एक बफ़र परिणाम (command.Buffered झंडा द्वारा इंगित) या एक आस्थगित इटरेटर लौट सकते हैं या तो। यदि मार्क using कथन के साथ पाठक को लपेटना था और एक पुनरावर्तक लौटाता था, तो कॉल (साइट) को कॉल करने के दौरान इसे (पाठक) का निपटारा किया जाएगा। जब वह पाठक सेट

finally 
{ 
    IDisposable disposable = reader; 
    try 
    { 
    } 
    finally 
    { 
     if (dispoable != null) 
     { 
      disposable.Dispose(); 
     } 
    } 
} 

: (इससे पहले कि वह आस्थगित परिणाम देता है लाइन में) null पाठक की स्थापना वह निपटारा होने से पाठक को रोकता है, क्योंकि अंत में ब्लॉक में उपयोग करते हुए इस में अनुवाद किया जाएगा तक null पर, इसका निपटारा नहीं किया गया है, और पाठक को इंगित करने वाला संदर्भ अभी भी जिंदा है। इस तरह, वह दोनों सामान्य कोडपैथ में पाठक का निपटान कर सकते हैं, लेकिन यदि स्थगित पुनरावर्तक से अनुरोध किया गया तो उसे जीवित रखें।

+0

अच्छा पकड़ो। बीटीडब्ल्यू - क्या आप जानते हैं कि वह क्यों लिखता है "ReadAsync का उपयोग नहीं कर सकता" _? रद्दीकरण टोकन के अलावा, और क्या हो सकता है? मुझे यकीन नहीं है कि मैं –

+0

@RoyiNamir में buffered भूमिका को समझता हूं, मुझे लगता है कि * 'ReadAsync' * का उपयोग नहीं कर सकता है, इस तथ्य के लिए कि वह एक एसिंक्रोनस इटरेटर वापस नहीं दे सकता है। आप एक एसिंक ऑपरेशन 'वापसी' नहीं कर सकते हैं। –

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