2016-11-24 14 views
5

मुझे एक अजीब समस्या मिल रही है जहां मैं कॉल से परिणामों को संग्रहीत प्रक्रिया में वापस करने में सक्षम हूं, लेकिन कोड पीछे से विफल रहता है।SqlDataReader की कनेक्शन प्रॉपर्टी शून्य

public IEnumerable<T> ExecuteStoredProcedure<T>(string storedProcedureName, IDataMapper<T> mapper, IDictionary<string, object> parameters) 
{ 
    using (var connection = new SqlConnection(connectionString)) 
    { 
     using (var cmd = new SqlCommand(storedProcedureName, connection)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      foreach (var key in parameters.Keys) 
      { 
       cmd.Parameters.AddWithValue(key, parameters[key]); 
      } 
      connection.Open(); 
      SqlDataReader reader = cmd.ExecuteReader(); 
      //return MapRecordsToDTOs(reader, mapper); 

      //let's test: 
      IEnumerable<T> result = MapRecordsToDTOs(reader, mapper); 
      var x = (new List<T>(result)).Count; 
      System.Diagnostics.Debug.WriteLine(x); 
      return result; 
     } 
    } 
} 


private static IEnumerable<T> MapRecordsToDTOs<T>(SqlDataReader reader, IDataMapper<T> mapper) 
{ 
    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
      System.Diagnostics.Debug.WriteLine(reader["Id"]); //what's going on... 
      yield return mapper.MapToDto((IDataRecord)reader); 
     } 
    } 
} 

इस कोड को कॉल किया जा रहा से पता चलता है कि चर x हमेशा पंक्तियों मैं अपने संग्रहित प्रक्रियाओं के लिए एक कॉल से देखने के लिए उम्मीद थी की संख्या का प्रतिनिधित्व करता है।

इसके अतिरिक्त मेरा डीबग आउटपुट आईडी मान दिखाता है जिसे मैं देखना चाहता हूं।

हालांकि, उन परिणामों के बाद, मुझे त्रुटि if (reader.HasRows) (यानी जो पहले ही निष्पादित कर दी गई है) से त्रुटि मिलती है। जिस ब्राउज़र से मैं इस अनुरोध का आह्वान करता हूं वह दिखाता है HTTP Error 502.3 - Bad Gateway

Screenshot of Error

Screenshot of HasRows Behaviour

मुझे लगता है कारण सिस्टम के लिए अलग से यह कैसे वास्तविक उपयोगकर्ता उत्पादन वापसी होगी करने के लिए की गणना डिबग के लिए ID और X मूल्यों है। इस प्रकार, यह उस बिंदु पर IENumerable मान प्राप्त करने के लिए आलसी ऑपरेशन करता है जिस पर उसे वापस करना होता है; केवल इस बिंदु से using कथनों ने निपटान विधियों को बुलाया है, और इस प्रकार पाठक का कनेक्शन शून्य है (यह तब होता है जब मैं reader डिबगिंग के दौरान चर के गुणों का निरीक्षण करता हूं)।

क्या किसी ने इस तरह के व्यवहार को पहले देखा है/क्या यह एक बग है; या क्या मैंने अभी कुछ स्पष्ट याद किया है?


अतिरिक्त कोड:

public interface IDataMapper<T> 
{ 
    T MapToDto(IDataRecord record); 
} 

public class CurrencyMapper: IDataMapper<CurrencyDTO> 
{ 
    const string FieldNameCode = "Code"; 
    const string FieldNameId = "Id"; 
    const string FieldNameName = "Name"; 
    const string FieldNameNum = "Num"; 
    const string FieldNameE = "E"; 
    const string FieldNameSymbol = "Symbol"; 

    public CurrencyMapper() { } 

    public CurrencyDTO MapToDto(IDataRecord record) 
    { 
     var code = record[FieldNameCode] as string; 
     var id = record[FieldNameId] as Guid?; 
     var name = record[FieldNameName] as string; 
     var num = record[FieldNameNum] as string; 
     var e = record[FieldNameE] as int?; 
     var symbol = record[FieldNameSymbol] as char?; 
     return new CurrencyDTO(id, code, num, e, name, symbol); 
    } 
} 

public class CurrencyRepository 
{ 

    const string SPReadAll = "usp_CRUD_Currency_ReadAll"; 

    readonly SqlDatabase db; 
    public CurrencyRepository() 
    { 
     db = new SqlDatabase(); //stick to SQL only for the moment for simplicity 
    } 
    public IEnumerable<CurrencyDTO> GetCurrencyCodes() 
    { 
     var mapper = new CurrencyMapper(); 
     return db.ExecuteStoredProcedure(SPReadAll, mapper); 
    } 
} 

public class CurrencyDTO 
{ 

    readonly Guid? id; 
    readonly string code; 
    readonly string num; 
    readonly int? e; 
    readonly string name; 
    readonly char? symbol; 

    public CurrencyDTO(Guid? id,string code,string num,int? e,string name, char? symbol) 
    { 
     this.id = id; 
     this.code = code; 
     this.num = num; 
     this.e = e; 
     this.name = name; 
     this.symbol = symbol; 
    } 

    public Guid? Id { get { return id; } } 
    public string Code { get { return code; } } 
    public string Num { get { return num; } } 
    public int? E { get { return e; } } 
    public string Name { get { return name; } } 
    public char? Symbol { get { return symbol; } } 
} 
+1

आप का निरीक्षण करने के (या अपने कोड में उपयोग) सिर्फ 'के बाद SqlDataReader पाठक = cmd.ExecuteReader' reader.HasRows' की कोशिश की है() ; 'और' MapRecordsToDTOs 'को कॉल करने से पहले? – McNets

+1

आप इसके साथ प्रयास कर सकते हैं: 'reader = cmd.ExecuteReaderAsync();' – McNets

+0

@mcNets: 'MapRecordsToDTOs' फ़ंक्शन पुष्टि करता है कि 'पाठक।HasRows' सच है क्योंकि यह उन पंक्तियों के माध्यम से फिर से सक्षम हो सकता है ताकि 'x' को सही मान प्राप्त हो सके, और' आईडी को 'Debug.WriteLine' द्वारा सही तरीके से आउटपुट किया जा सके। बयान। – JohnLBevan

उत्तर

2

मैं अस्थायी रूप से एक समाधान है जो इस समस्या का समाधान क्रियान्वित किया है।

यह काम करता है:

private static IEnumerable<T> MapRecordsToDTOs<T>(SqlDataReader reader, IDataMapper<T> mapper) 
{ 
    var list = new List<T>(); //use a list to force eager evaluation 
    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
      list.Add(mapper.MapToDto((IDataRecord)reader)); 
     } 
    } 
    return list.ToArray(); 
} 

के रूप में मूल करने का विरोध किया:

private static IEnumerable<T> MapRecordsToDTOs<T>(SqlDataReader reader, IDataMapper<T> mapper) 
{ 
    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
      yield return mapper.MapToDto((IDataRecord)reader); 
     } 
    } 
} 

अंतर किया जा रहा मैं ऐसी है कि वह केवल सूची में परिणामों के माध्यम से दोहराता कोड इटरेटर से प्रभावित के लिए कदम; और IDisposable ऑब्जेक्ट्स से संबंधित आवश्यकताओं को समझने के लिए संकलक पर भरोसा नहीं करता है।

यह मेरी समझ है कि संकलक मेरे लिए इसे संभालने में सक्षम होना चाहिए (यहां पुष्टि की गई: https://stackoverflow.com/a/13504789/361842), इसलिए मुझे लगता है कि यह कंपाइलर में एक बग है।

यहाँ रिपोर्ट किया गया: https://connect.microsoft.com/VisualStudio/feedback/details/3113138

अतिरिक्त डेमो कोड यहाँ: https://gist.github.com/JohnLBevan/a910d886df577e442e2f5a9c2dd41293/

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