#c# #sql-server
#c# #sql-сервер
Вопрос:
Когда вызывается метод, я хочу вернуть значение true, если имя уже существует, и значение false в противном случае. Мой пример кода приведен ниже.
private bool NameDuplicate(string txt)
{
conn.Open();
com.Connection = conn;
com.CommandText = "select Cat_d from Category";
SqlDataReader dr = com.ExecuteReader();
bool found = false;
while (dr.Read())
{
if (txt == dr["Cat_d"].ToString())
{
found = true;
}
else
{
found = false;
}
}
conn.Close();
return found;
}
if (NameDuplicate(cat_txt))
{
MessageBox.Show("Already exist!");
}
Пожалуйста, помогите мне объяснить.
Комментарии:
1. зачем загружать весь набор данных в память, когда вы можете просто выполнить простой запрос к базе данных? например, выберите Cat_d из категории, где Cat_d = txt, а затем просто верните true, если есть какие-либо результаты.
2. Joe_Dm Спасибо. Я попробую так, как вы сказали.
Ответ №1:
Ниже приведен некоторый код, который вы можете использовать для этого, но я хочу отметить, что реально вы, вероятно, не стали бы утруждать себя выполнением этого на c #. Вы бы добавили УНИКАЛЬНОЕ ограничение / индекс или первичный ключ в базу данных и просто вставили значения из c #, обрабатывая случай, когда возникает исключение, поскольку значение уже существует. Реализация логики уникальности в c #, когда sqlserver способен делать это вечно, на самом деле «покупает собаку и лает сам»
private bool NameDuplicate(string txt)
{
using(var con = new SqlConnection(YOUR CONNECTION STRING HERE)
using(var com = new SqlCommand("select count(*) from Category where cat_d = @c", con){
con.Open();
com.Parameters.Add("@c", SqlDbType.VarChar, 999).Value = txt;
var o = com.ExecuteScalar();
con.Close(); //optional; dispose will do this too
return Convert.ToInt32(o) != 0;
}
}
if (NameDuplicate(cat_txt))
{
MessageBox.Show("Already exist!");
}
Всегда используйте блоки using, чтобы убедиться, что связанные с БД ресурсы удалены, и не используйте их повторно (кажется, ваше соединение и команда определены где-то еще, и вы храните их в течение длительного времени / повторно используете их?
Чтобы проверить существование, мы можем (упрощенно) подсчитать количество записей, выполнить масштабирование и проверить возвращенное число. Возможно, было бы немного быстрее использовать запрос EXISTS, но я выбрал этот маршрут, потому что он легко читается и упрощает код.
Вот запрос, который вы могли бы использовать вместо select count для достижения того же эффекта. Было бы очень полезно использовать его, если столбец, который вы ищете, не проиндексирован, потому что, как указывает Аарон, нет никакого смысла в том, чтобы sqlserver считал всю таблицу целиком, когда реально он может остановиться, как только найдет искомое значение и выдаст тот же ответ:
SELECT CASE WHEN EXISTS(SELECT null FROM Category where cat_d = @c) THEN 1 ELSE 0 END
Комментарии:
1. В целом отличный совет. Хотя зачем считать? Почему бы просто не использовать
TOP (1) cat_d
(с приличнымORDER BY
значением, если вы достаточно знаете о любых индексах, которые могут существовать, которые имеютcat_d
в ключе)? «Есть ли песок на пляже?» «Ну, я нашел одну песчинку, но позвольте мне сосчитать их все, прежде чем я дам вам ответ!»2. (Честно говоря, я думаю, что EXISTS является более безопасным подходом и все еще относительно самодокументируется.)
3. @AaronBertrand Я понимаю вашу точку зрения, но в данном случае я не вижу вреда в использовании count, потому что кажется, что запрос используется для предотвращения дубликатов (а также должен быть проиндексирован), поэтому в любом случае будет только 0 или 1, и индекс будет знать количество, поэтому я полагаю, что на самом деле мы не считаем миллиард песчинок, чтобы определить наличие песка, больше похоже на то, что мы идем на пляж с 0 или 1 песчинками, и кто-то, кто может сказать нам это, когда мы прибудем.. Однако я добавил запрос EXISTS, который является заменой.