2012-04-20 1 views
7

ho questo codice:Restituzione di uno SqlDataReader

public static SqlDataReader GetGeneralInformation (int RecID) 
{ 
    using (var conn = new SqlConnection(GetConnectionString())) 
    using (var cmd = conn.CreateCommand()) 
    { 
     conn.Open(); 
     cmd.CommandText = 
     @"SELECT cs.Status, cs.Completed 
      FROM NC_Steps s 
      INNER JOIN NC_ClientSteps cs 
       ON cs.RecID = s.RecID 
      WHERE cs.ClientID = 162 
      AND s.RecID = @value"; 
     cmd.Parameters.AddWithValue("@value", RecID); 
     using (var reader = cmd.ExecuteReader()) 
     { 
      if (reader.Read()) 
      { 
       return reader; 
      } 
      return null; 
     } 
    } 
} 

Come faccio riferimento a questo?

Ho provato questo ma non funziona.

SqlDataReader reader = GeneralFunctions.GetGeneralInformation(); 

Inoltre, come leggerei dal lettore?

Reader.GetString(reader.GetOrdinal("Status")) 

Edit:

Ora sto ottenendo il seguente errore:

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Ecco il codice aggiornato:

public static IEnumerable<IDataRecord> GetGeneralInformation (int ClientID) 
{ 
    using (var conn = new SqlConnection(GetConnectionString())) 
    using (var cmd = conn.CreateCommand()) 
    { 
     conn.Open(); 
     cmd.CommandText = 
     @"SELECT i.GoLiveDate, i.FirstBonusRun, i.TechFName, i.TechLName, i.TechEmail, i.TechPhone, i.WebISPFName, i.WebISPLName, 
      i.WebISPEmail, i.WebISPPhone, i.FullFillFName, i.FullFillLName, i.FullFillEmail, i.FullFillPhone, d.FName, 
      d.LName, d.HomePhone, d.Email 
      FROM NC_Information i 
      INNER JOIN Distributor d 
      ON d.DistID = i.ClientID 
      WHERE clientID = @value"; 
     cmd.Parameters.AddWithValue("@value", ClientID); 
     using (var reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       yield return reader; 
      } 
      yield return null; 
     } 
    } 
} 

protected void Page_Load(object sender, EventArgs e) 
{ 
    IEnumerable<IDataRecord> reader = GeneralFunctions.GetGeneralInformation((int)Session[ "DistID" ]); 

    //string result = GeneralFunctions.GetGeneralInformation(Globals.GeneralInformation).First()[ "Status" ].ToString(); 
} 
+1

Perché non riesci a leggerlo come qualsiasi altro SqlDataReader? Fallisce? Se è così, è a causa delle tue istruzioni 'using'. Stai chiudendo la connessione prima di usare il lettore. –

+0

@JohnSaunders Sto cercando di restituire il lettore stesso. Non sono sicuro del modo migliore per realizzare ciò che voglio fare. Fondamentalmente è un modulo di asp.net che viene popolato con i dati di un database. L'unico modo in cui potrei pensare di farlo è restituire il lettore stesso in modo da poter inserire le informazioni nelle caselle di testo di asp.net. –

+1

È possibile restituire un oggetto popolato dal lettore. E tu non hai ancora detto cosa non ha funzionato. –

risposta

15

Il problema è che lasciare la funzione (tramite la dichiarazione di ritorno) ti prende a calci fuori dal using blocchi e quindi SqlDataReader e SqlConnections in uso sono eliminati. Per aggirare il problema, provare a cambiare la firma funzione come questa:

public static IEnumerable<IDataRecord> GetGeneralInformation (int RecID) 

e quindi aggiornare il centro della funzione come questa:

using (var reader = cmd.ExecuteReader()) 
{ 
    while (reader.Read()) 
    { 
     yield return reader; 
    } 
} 

Per la finale "Come leggo da esso? " parte, potrebbe assomigliare a questo:

string result = reader.First()["Status"].ToString(); 
+0

Potresti aiutarmi a capire cosa restituisce IEnumerable e yield? Se no posso cercarli, apprezzo la risposta in entrambi i casi. –

+0

@BrokenGlass - prova, funziona benissimo. Il codice viene "sollevato" in una classe separata dietro le quinte e il dispose non viene raggiunto fino a dopo l'enumerazione. –

+0

@JamesWilson La parola chiave yield crea ciò che viene chiamato "Iterator". È un oggetto che sa come ricorrere ad una collezione di qualche tipo. IEnumerable è un altro modo per descrivere le parti importanti di un SqlDataReader. Puoi usarlo in un ciclo foreach (;;). –

-1

Per definizione, una dichiarazione using si suppone di disporre di un oggetto dopo che è stato chiamato.

Pertanto, dopo aver restituito il lettore di dati, viene eliminato.

+1

-1: sicuramente _can_ ritorna da un blocco 'using'! –

+0

Di cosa stai parlando? Non hai bisogno di un rendimento. Vai a provarlo. Potrebbe non funzionare, ma verrà sicuramente compilato. –

0

Il problema è che si sta creando la connessione al database all'interno del metodo.

Se si sta andando a condividere risorse di database tra diversi metodi, spostare SqlConnection al di fuori di questo ambito.

In questo modo è possibile restituire il Reader da questa funzione e persisterà.

Inoltre, non. Leggi() all'interno di questa funzione, è sufficiente restituire l'oggetto.

6

Aggiungere la stringa di connessione alla sezione AppSettings in app.config o web.config.

public string GetSqlConnection() 
    { 
     return System.Configuration.ConfigurationManager.AppSettings["SqlConnectionString"]; 
    } 

// funzione per restituire SqlDataReader risultati

public SqlDataReader executeReader(string sql, SqlParameter[] parameters=null) 
    { 
     SqlConnection conn = new SqlConnection(); 
     conn.ConnectionString = GetSqlConnection(); 
     conn.Open(); 
     SqlCommand cmd = new SqlCommand(); 
     cmd.Connection = conn; 
     cmd.CommandText = sql; 
     if (parameters != null) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      foreach (SqlParameter p in parameters) 
      { 
       cmd.Parameters.Add(p); 
      } 
     } 
     else 
     { 
      cmd.CommandType = CommandType.Text; 
     } 
     SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); 
     return reader; 
    } 

Per utilizzare la funzione:

 string query = @"SELECT cs.Status, cs.Completed 
     FROM NC_Steps s 
     INNER JOIN NC_ClientSteps cs 
      ON cs.RecID = s.RecID 
     WHERE cs.ClientID = 162 
     AND s.RecID = @value"; 
     //you can add more parameters by adding commas 
     var parameters = new SqlParameter[] { 
      new SqlParameter("@value", RecID) 
      }; 

     SqlDataReader dr = executeReader(query, parameters); 
     while (dr.Read()) 
     { 
      //fill your controls with data 
     } 
     dr.Close();