2016-10-31 12 views
1

Я пытаюсь вернуть данные с помощью IEnumerable с заданными полями, где я вызываю метод, которым я хочу ссылаться на данные с заданным именем поля и возвращать их.Использование IEnumerable <IDataRecord> для возврата данных

Пример, вот функция

public IEnumerable<IDataRecord> GetSomeData(string fields, string table, string where = null, int count = 0) 
    { 
     string sql = "SELECT @Fields FROM @Table WHERE @Where"; 

     using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug))) 
     using (SqlCommand cmd = new SqlCommand(sql, cn)) 
     { 
      cmd.Parameters.Add("@Fields", SqlDbType.NVarChar, 255).Value = where; 

      cn.Open(); 

      using (IDataReader rdr = cmd.ExecuteReader()) 
      { 
       while (rdr.Read()) 
       { 
        yield return (IDataRecord)rdr; 
       } 
      } 
     } 
    } 

Призвание:

IEnumerable<IDataRecord> data = bw.GetSomeData("StaffCode, Perms", "BW_Staff", "StaffCode = 'KAA'"); 

Что я должен сделать, чтобы вернуть данные так или каким образом?

string staffCode = data["StaffCode"].ToString(); 
string perms = data["Perms"].ToString(); 

Спасибо за любую помощь

+0

«поле» либо должно быть массивом строк или разделители строки, которая разделяется на ограничителе. Затем зациклируйте этот массив полей, чтобы построить вашу строку cmd.Parameters.Add. –

ответ

1

переменных данных представляет собой набор строк. Вам нужно перебирать коллекцию, чтобы делать что-то интересное с каждой строкой.

foreach (var row in data) 
{ 
    string staffCode = row["StaffCode"].ToString(); 
    string perms = row["Perms"].ToString(); 
} 

Update:

Основываясь на ваш комментарий, что вы только ожидаете GetSomeData (...), чтобы вернуть одну строку, я хотел бы предложить один из двух вещей.

Измените подпись GetSomeData, чтобы вернуть IDataRecord. и удалить «выход» из реализации.

public IDataRecord GetSomeData(string fields, string table, string where = null, int count = 0) 
    { 
     string sql = "SELECT @Fields FROM @Table WHERE @Where"; 

     using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug))) 
     using (SqlCommand cmd = new SqlCommand(sql, cn)) 
     { 
      cmd.Parameters.Add("@Fields", SqlDbType.NVarChar, 255).Value = where; 

      cn.Open(); 

      using (IDataReader rdr = cmd.ExecuteReader()) 
      { 
       while (rdr.Read()) 
       { 
        return (IDataRecord)rdr; 
       } 
      } 
     } 
    } 
} 

Или

var row = data.FirstOrDefault(); 
if (row != null) 
{ 
    string staffCode = row["StaffCode"].ToString(); 
    string perms = row["Perms"].ToString(); 
} 

Примечание:

Ваша реализация GetSomeData является неполной. Вы даже не используете несколько параметров, самое главное параметр полей. И концептуально в SQL вы не можете параметризовать, какие поля возвращаются или какая таблица используется (и т. Д.), А вам нужно построить динамический запрос и выполнить его.

Update 2

Вот реализация GetSomeData, что создает надлежащий запрос (в C# 6, дай мне знать, если вам это нужно в более ранней версии).

public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0) 
{ 
    var predicate = string.IsNullOrWhiteSpace(where) ? "" : " WHERE " + where; 
    string sql = $"SELECT { string.Join(",", fields) } FROM {table} {predicate}"; 

    using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug))) 
    using (SqlCommand cmd = new SqlCommand(sql, cn)) 
    { 
     cn.Open(); 

     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       yield return (IDataRecord)rdr; 
      } 
     } 
    } 
} 

И вот как вы могли бы использовать его.

IEnumerable<IDataRecord> data = bw.GetSomeData(new[] { "StaffCode", "Perms" }, "BW_Staff", "StaffCode = 'KAA'"); 

Вы можете либо перечислить его, либо позвонить .FirstOrDefault, это ваш выбор. Каждый раз, когда вы вызываете GetSomeData, он запускает запрос.

Update 3

GetSomeData реализован с более ранними версиями C#

public IEnumerable<IDataRecord> GetSomeData(IEnumerable<string> fields, string table, string where = null, int count = 0) 
{ 
    var predicate = string.IsNullOrEmpty(where) ? "" : " WHERE " + where; 
    string sql = string.Format("SELECT {0} FROM {1} {2}", string.Join(",", fields), table, predicate); 

    using (SqlConnection cn = new SqlConnection(db.getDBstring(Globals.booDebug))) 
    using (SqlCommand cmd = new SqlCommand(sql, cn)) 
    { 
     cn.Open(); 

     using (IDataReader rdr = cmd.ExecuteReader()) 
     { 
      while (rdr.Read()) 
      { 
       yield return (IDataRecord)rdr; 
      } 
     } 
    } 
} 
+0

Означает ли это, что он вызывает запрос снова и снова? Любой способ не использовать цикл?спасибо –

+0

Возможно, я не понимаю ваш оригинальный вопрос. Можете ли вы точно описать, чего вы пытаетесь достичь? –

+0

Хотя я могу понять, что поля должны быть массивом строк, я хочу вызвать метод один раз, чтобы он выполнял один запрос ... Я вводил имена полей ... field1, field2, field3 в качестве параметров .. «Выберите поле1, field2, field3 ... ". вызывать метод как массив ... и выводить данные с заданным именем поля. например array ["field1"], array ["field2"] и т. д. –