2014-10-14 4 views
0

Мне нужно получить таблицу и проверить, существует ли переменная 'verb' в одном из трех столбцов, а затем передать значения этой конкретной строки в объект Verb, как указано ниже.C# SqlDataReader проверяет, существует ли запись таблицы?

В этом коде, однако, условие if, которое читает столбцы, пропускает это условие, как если бы поле не было в таблице, даже если оно действительно выполняется. Есть ли лучшие способы сделать это?

public static Verb GetVerbs(string verb) 
{ 
    List<string> Verbs = new List<string>(); 
    Verb v = new Verb(); 

    SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=QABase;Integrated Security=True"); 

    try 
    { 
     conn.Open(); 
    } 
    catch (Exception e) 
    { 
     System.Console.WriteLine(e.ToString()); 
    } 

    try 
    { 
     SqlDataReader myReader = null; 

     SqlCommand myCommand = new SqlCommand("select * from EnglishVerbs", conn); 

     myReader = myCommand.ExecuteReader(); 

     while (myReader.Read()) 
     { 
      if ((myReader["BaseForm"].ToString().ToLower().Contains(verb.ToLower())) 
       || (myReader["PastForm"].ToString().ToLower().Contains(verb.ToLower())) 
       || (myReader["PastPartForm"].ToString().ToLower().Contains(verb.ToLower()))) 
      { 
       v.BaseTense = Convert.ToString(myReader["BaseForm"]); 
       v.PastTense = Convert.ToString(myReader["PastForm"]); 
       v.PastParticiple = Convert.ToString(myReader["PastPartForm"]); 
      } 
      else 
      { 
       //row doesnt exist 
       v.BaseTense = null; 
       v.PastTense = null; 
       v.PastParticiple = null; 
      } 
     } 
    } 
    catch (Exception e) 
    { 
     System.Console.WriteLine(e.ToString()); 
    } 

    try 
    { 
     conn.Close(); 
    } 
    catch (Exception e) 
    { 
     System.Console.WriteLine(e.ToString()); 
    } 

    return v; 
} 
+0

Попробуйте это: if ((myReader [0] .ToString(). ToLower(). Содержит (verb.ToLower())) || (myReader [1] .ToString(). ToLower(). Содержит (verb.ToLower())) || (myReader [2] .ToString(). ToLower(). Содержит (verb.ToLower()))) –

+2

почему так много пытаются поймать ???? – Dhwani

ответ

1

вы выбираете все EnglishVerbs и перебирать их. Если вы обнаружите, что глагол содержит задание, иначе вы назначаете null s. Однако вы не нарушаете цикл, когда найдете глагол. Если последний элемент в списке не содержит ваш глагол, как вы можете догадаться, ему назначается null. Измените свой цикл, чтобы что-то вроде:

while (myReader.Read()) 
{ 
    if (myReader["BaseForm"].ToString().ToLower().Contains(verb.ToLower()) || 
     myReader["PastForm"].ToString().ToLower().Contains(verb.ToLower()) || 
     myReader["PastPartForm"].ToString().ToLower().Contains(verb.ToLower())) 
    { 
     v.BaseTense  = Convert.ToString(myReader["BaseForm"]); 
     v.PastTense  = Convert.ToString(myReader["PastForm"]); 
     v.PastParticiple = Convert.ToString(myReader["PastPartForm"]); 

     break; 
    } 
    else 
    { 
     v.BaseTense = null; 
     v.PastTense = null; 
     v.PastParticiple = null; 
    } 
}   

Кроме того, вы не должны назначать null в else блока каждый раз. Просто назначьте его перед циклом один раз. Как:

v.BaseTense = null; 
v.PastTense = null; 
v.PastParticiple = null; 

while (myReader.Read()) 
{ 
    if (myReader["BaseForm"].ToString().ToLower().Contains(verb.ToLower()) || 
     myReader["PastForm"].ToString().ToLower().Contains(verb.ToLower()) || 
     myReader["PastPartForm"].ToString().ToLower().Contains(verb.ToLower())) 
    { 
     v.BaseTense  = Convert.ToString(myReader["BaseForm"]); 
     v.PastTense  = Convert.ToString(myReader["PastForm"]); 
     v.PastParticiple = Convert.ToString(myReader["PastPartForm"]); 

     break; 
    } 
} 

НО это не самое лучшее, что можно сделать. Я ответил в соответствии с вашим стилем программирования. Однако лучше всего сделать фильтрацию в стороне базы данных, изменив ваш запрос, как в ответе GarethD. Таким образом, вы получаете меньше элементов из базы данных, это огромный прирост производительности. Передача данных между уровнями проектов (уровни клиент-приложений-базы данных) должна быть самой большой проблемой.

+0

Очень информативно, Большое вам спасибо, и это сработало! :) – ProgrammingFreak

3

Почему бы просто не проверить непосредственно в SQL? Ваш SQL будет что-то вроде:

SELECT BaseForm, PastForm, PastPartForm 
FROM EnglishVerbs 
WHERE @Verb IN (BaseForm, PastForm, PastPartForm); 

Или, если вы хотите только частичные совпадения было бы:

SELECT BaseForm, PastForm, PastPartForm 
FROM EnglishVerbs 
WHERE BaseForm LIKE '%' + @Verb + '%' 
OR  PastForm LIKE '%' + @Verb + '%' 
OR  PastPartForm LIKE '%' + @Verb + '%'; 

SQL лучше оборудованный для обработки данных на основе наборов, как это, и это позволяет избежать сетевого трафика извлечения всей таблицы, а затем накладные расходы на цикл по каждой строке. Учитывая количество английских глаголов, я бы предположил, что вы не хотите возвращать все из них в приложение для каждого поиска!

Тогда вы можете назвать это, используя что-то вроде:

public static Verb GetVerbs(string verb) 
{ 
    Verb v = new Verb(); 

    string sql = @"SELECT BaseForm, PastForm, PastPartForm 
        FROM EnglishVerbs 
        WHERE @Verb IN (BaseForm, PastForm, PastPartForm);"; 

    string connString = "Data Source=.;Initial Catalog=QABase;Integrated Security=True"; 
    using (var connection = new SqlConnection(connString)) 
    using (var command = new SqlCommand(sql, connection)) 
    { 
     command.Parameters.Add("@Verb", SqlDbType.VarChar, 50).Value = verb; 
     connection.Open(); 

     using (var reader = command.ExecuteReader()) 
     if (reader.Read()) 
     { 
      v.BaseTense = Convert.ToString(reader["BaseForm"]); 
      v.PastTense = Convert.ToString(reader["PastForm"]); 
      v.PastParticiple = Convert.ToString(reader["PastPartForm"]); 
     } 
    } 
    return v; 
} 

нотабене Я удалил все ваши блоки try/catch, потому что они не используются! Если вы должны использовать try/catch, просто используйте один и уловите определенные исключения, прежде чем ловить общие исключения. Также очень неплохо сделать что-то значимое с вашим исключением, например, зарегистрировать его, если вы собираетесь его поймать, а не просто записать его на консоль.

Это определенно хорошая идея, чтобы выйти из метода после ловли его, если ваш первоначальный вызов conn.Open(); бросает исключение, ваш метод счастливо продолжает по-прежнему использовать соединение. Это будет означать, что больше исключений.

Грубый набросок может быть что-то вроде:

try 
{ 
    using (var connection = new SqlConnection(connString)) 
    using (var command = new SqlCommand(sql, connection)) 
    { 
     command.Parameters.Add("@Verb", SqlDbType.VarChar, 50).Value = verb; 
     connection.Open(); 

     using (var reader = command.ExecuteReader()) 
     if (reader.Read()) 
     { 
      v.BaseTense = Convert.ToString(reader["BaseForm"]); 
      v.PastTense = Convert.ToString(reader["PastForm"]); 
      v.PastParticiple = Convert.ToString(reader["PastPartForm"]); 
     } 
    } 
} 
catch (SqlException e) 
{ 
    //Log the exception or do something else meaningful 
    throw; 
} 
catch (Exception e) 
{ 
    //Log the exception or do something else meaningful 
    throw; 
} 
+0

Спасибо! Это тоже работает! – ProgrammingFreak

1

Есть несколько улучшений, которые вы можете внести в опубликованный код.

Прежде всего, было бы целесообразно, чтобы база данных сделать работу поиск строки (ы):

SqlCommand myCommand = new SqlCommand("select * from EnglishVerbs where BaseForm = @VerbToFind or PastForm = @VerbToFind or PastPartForm = @VerbToFind", conn); 
myCommand.Parameters.AddWithValue("VerbToFind", verb.ToLower()); 

При этом вы рассказываете базу данных, чтобы найти строки, в которых по крайней мере один из В столбцах содержится глагол, который вы омываете. В зависимости от столбцов collation вам может потребоваться обработка чувствительности к регистру. Предполагая, что у вас есть глаголы, хранящиеся в нижнем регистре в базе данных, вышеуказанное должно работать. Обратите внимание, что может быть найдено несколько строк.

Возможно, вы также поменяете место обработки ошибок, а также вы должны обернуть объект IDisposable в статьях using. Это будет означать, что, как только вы закончите с объектами, которые они будут автоматически очищены, даже если произошло исключение:

try 
{ 
    using(SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=QABase;Integrated Security=True") 
    { 
     conn.open(); 
     using(SqlCommand myCommand = new SqlCommand("select * from EnglishVerbs where BaseForm = @VerbToFind or PastForm = @VerbToFind or PastPartForm = @VerbToFind", conn)) 
     { 
      myCommand.Parameters.AddWithValue("VerbToFind", verb.ToLower()); 
      using(myReader = myCommand.ExecuteReader()) 
      { 
       while (myReader.Read()) 
       { 
        v = new Verb(); 
        v.BaseTense = Convert.ToString(myReader["BaseForm"]); 
        v.PastTense = Convert.ToString(myReader["PastForm"]); 
        v.PastParticiple = Convert.ToString(myReader["PastPartForm"]); 
        verbsToReturn.Add(v); 
       } 
      } 
     } 
    } 
} 
catch(Exception e) 
{ 
    System.Console.WriteLine(e.ToString()); 
    throw; //Rethrow exception to let caller know that something went wrong 
} 

Все это может выглядеть примерно так:

public static IEnumerable<Verb> GetVerbs(string verb) 
{ 
    if (verb == null) 
     throw new ArgumentException("verb cannot be null"); 
    List<Verb> verbsToReturn = new List<Verb>(); 
    Verb v = null; 

    try 
    { 
     using(SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=QABase;Integrated Security=True") 
     { 
      conn.open(); 
      using(SqlCommand myCommand = new SqlCommand("select * from EnglishVerbs where BaseForm = @VerbToFind or PastForm = @VerbToFind or PastPartForm = @VerbToFind", conn)) 
      { 
       myCommand.Parameters.AddWithValue("VerbToFind", verb.ToLower()); 
       using(myReader = myCommand.ExecuteReader()) 
       { 
        while (myReader.Read()) 
        { 
         v = new Verb(); 
         v.BaseTense = Convert.ToString(myReader["BaseForm"]); 
         v.PastTense = Convert.ToString(myReader["PastForm"]); 
         v.PastParticiple = Convert.ToString(myReader["PastPartForm"]); 
         verbsToReturn.Add(v); 
        } 
       } 
      } 
     } 
    } 
    catch(Exception e) 
    { 
     System.Console.WriteLine(e.ToString()); 
     throw; //Rethrow exception to let caller know that something went wrong 
    } 

    return verbsToReturn; 
} 
Смежные вопросы