wtorek, 12 czerwca 2018

C# - komunikacja z baza danych Sql

W tym poście chciałbym opisać sposób komunikacji z bazą danych SQL.

[Źródło: https://docs.microsoft.com/en-us/dotnet/]

Program:


Na samym początku należy zdeklarować biblioteki jakie będą potrzebne do nawiązania komunikacji z bazą danych SQL.

  1. using System.Data.Sql;
  2. using System.Data.SqlClient;
  3. using System.Data.SqlTypes;

Nawiązania połączenia wygląda następująco:

  1. public class sqlCon
  2. {
  3.    protected static SqlConnection sqlCon;
  4.    public static bool connectWithSqlDb()
  5.    {
  6.        sql.sqlConectionInfo.readConData();
  7.        string conString = sql.sqlConectionInfo.prepareConString();
  8.        sqlCon= new SqlConnection(conString);
  9.        try
  10.        {
  11.            sqlCon.Open();
  12.            sqlCon.Close();
  13.            return true;
  14.        }
  15.        catch
  16.        {
  17.            return false;
  18.        }
  19.    }
  20. }

Klasa powyżej odpowiada za nawiązanie i przetestowanie połączeni z bazą danych. Na samym początku pobiera informacje o połączeniu, po czym przygotowywany jest string z połączeniem. W przypadku poprawnego otwarcia bazy zwracana jest wartość True, gdy wystąpił błąd zwracana jest wartość False.

  1. public class sqlConectionInfo : checkIfConStringData
  2. {
  3.     private static string serverNameStr = "";
  4.     private static string dataBaseNameStr = "";
  5.     private static string conStr = "";
  6.     private static string userName = "";
  7.     private static string userPassword = "";
  8.     public static string ap_serverNameStr
  9.     {
  10.         get { return serverNameStr; }
  11.         private set { serverNameStr = value; }
  12.     }
  13.     public static string ap_dataBaseNameStr
  14.     {
  15.         get { return dataBaseNameStr; }
  16.         private set { dataBaseNameStr = value; }
  17.     }
  18.     public static string ap_conStr
  19.     {
  20.         get { return conStr; }
  21.         private set { conStr = value; }
  22.     }
  23.     public static string ap_userName
  24.     {
  25.         get { return userName; }
  26.         private set { userName = value; }
  27.     }
  28.     public static string ap_userPassword
  29.     {
  30.         get { return userPassword; }
  31.         private set { userPassword = value; }
  32.     }
  33.     public static void readConData()
  34.     {
  35.         ap_serverNameStr = Properties.Settings.Default.serverNameRetData;
  36.         ap_dataBaseNameStr = Properties.Settings.Default.dataBaseNameRetData;
  37.         ap_conStr = checkIfConStringData.checkIfConStringWriteInMemIfNotWriteDef(Properties.Settings.Default.conStringRetData);
  38.         ap_userName = Properties.Settings.Default.userNameRetData;
  39.         ap_userPassword = Properties.Settings.Default.userPassRetData;
  40.     }
  41.     public static string prepareConString()
  42.     {
  43.         return String.Format(ap_conStr, ap_serverNameStr, ap_dataBaseNameStr, ap_userName, ap_userPassword);
  44.     }
  45. }
  46. public class checkIfConStringData
  47. {
  48.     private const string conStrDefault = "Server={0};Database={1};user id={2};Password={3};Integrated       Security=True;MultipleActiveResultSets=True";
  49.     protected static string checkIfConStringWriteInMemIfNotWriteDef(string conString)
  50.     {
  51.         if (conString == "")
  52.         {
  53.             return conStrDefault;
  54.         }
  55.         return conString;
  56.     }
  57. }

String z danymi o połączeniu przyjmuje takie parametry jak nazwa serwera (tutaj podaje się również port po przecinku np. nazwaserwera,port), nazwę bazy danych z którą dokonywane jest połączenie, login, hasło. Następnie jest parametr Integrated Securit, który ustawiony na true oznacza, że do uwierzytelniania wykorzystywane są dane dla konta Windows. Kolejny parametr czyli MultipleActiveResultSets dla true pozwala na używanie wielu instancji przy jednym połączeniu.

Komunikacja z bazą odbywa się poprzez zapytania SQL.

Aby odczytać wszystkie informacje w bazie można posłużyć się następującą funkcją:

  1. public static DataSet readWholeTable()
  2. {
  3.     DataSet ds = new System.Data.DataSet();
  4.     SqlCommand command;
  5.     using (sqlCon)
  6.     {
  7.         sqlCon= new SqlConnection(sql.sqlConectionInfo.prepareConString());
  8.         cnnCards.Open();
  9.         command = new SqlCommand(sql.sqlComm.getAllDatasqlCon);
  10.         SqlDataAdapter da = new SqlDataAdapter(command);
  11.         da.Fill(ds);
  12.         sqlCon.Close();
  13.         da.Dispose();
  14.     }
  15.     return ds;
  16. }

Tutaj tworzony jest element klasy DataSet, który będzie przechowywał odczytane dane. Wykonywana komenda wygląda następująco:

  1. public const string getAllData = "SELECT * FROM name_of_table;";

W przypadku odczytu jednej komuny można posłużyć się następującą operacją:

  1. public static List<string> readColumn()
  2. {
  3.     List<string> list = new List<string>();
  4.     DataTable ds = new System.Data.DataTable();
  5.     using (sqlCon)
  6.     {
  7.         try
  8.         {
  9.             sqlCon= new SqlConnection(sql.sqlGetDataConInfo.prepareConString());
  10.             sqlCon.Open();
  11.         }
  12.         catch
  13.         {
  14.             list = null;
  15.             sqlCon.Close();
  16.             return list;
  17.         }
  18.        
  19.         /* readColumn = "SELECT column_name FROM tablename;"; */
  20.         using (SqlCommand cmd = new SqlCommand(sql.sqlComm.readColumn, sqlCon))
  21.         {
  22.             try
  23.             {
  24.                 using (SqlDataReader reader = cmd.ExecuteReader())
  25.                 {
  26.                     if (reader != null)
  27.                     {
  28.                         while (reader.Read())
  29.                         {
  30.                             list.Add(reader[sql.sqlPracComm.localizationColumnName].ToString());
  31.                         }
  32.                     }
  33.                 }
  34.             }
  35.             catch
  36.             {
  37.                 list = null;
  38.                 sqlCon.Close();
  39.                 return list;
  40.             }
  41.         }
  42.     }
  43.     sqlCon.Close();
  44.     return list;
  45. }

Tutaj dane zostają zapisane do stworzonej listy, która po wykonaniu poprawnego odczytu zostaje zwrócona.

Dodanie nowego rekordu do bazy:

  1. public static bool insertIntoDB(string name, string surname, string number)
  2. {
  3.     string insertData = "insert into tableName ([id], [name_first], [name_last], [numberData]) " +
  4.                                 "values (@id, @name, @surname, @numberData);";
  5.     int affectedRows = 0;
  6.     SqlCommand command;
  7.     Int32 id = readMaxIDInDb();
  8.     if(id == -1)
  9.     {
  10.         return false;
  11.     }
  12.     id += 1;
  13.     try
  14.     {
  15.         sqlCon = new SqlConnection(sql.sqlConectionInfo.prepareConString());
  16.         sqlCon.Open();
  17.         command = new SqlCommand(insertData, sqlCon);
  18.         command.Parameters.AddWithValue("@id", id.ToString());
  19.         command.Parameters.AddWithValue("@name", name);
  20.         command.Parameters.AddWithValue("@surname", surname);
  21.         command.Parameters.AddWithValue("@numberData", number);
  22.         affectedRows = command.ExecuteNonQuery();
  23.         sqlCon.Close();
  24.     }
  25.     catch
  26.     {
  27.         return false;
  28.     }
  29.     if (affectedRows > 0)
  30.     {
  31.         return true;
  32.     }
  33.     return false;
  34. }

Tutaj najpierw tworzony jest nowy rozkaz, następnie sprawdzany jest aktualny numer ID w bazie po czym dodawane są dane i komenda zostaje wykonana. Gdy wystąpi błąd lub liczba wykonanych operacji będzie mniejsza od 1 to zwrócona zostaje wartość false, oznaczająca błąd wykonywania komendy.

  1. private static Int32 readMaxIDInDb()
  2. {
  3.     Int32 readedIdValue = -1;
  4.     SqlCommand command;
  5.     try
  6.     {
  7.         sqlCon = new SqlConnection(sql.sqlConectionInfo.prepareConString());
  8.         sqlCon.Open();
  9.         /* readMaxIdValue = "SELECT MAX(cards.id) FROM tablename;"; */
  10.         command = new SqlCommand(sql.sqlCardsComm.readMaxIdValue, sqlCon);
  11.         readedIdValue = Convert.ToInt32(command.ExecuteScalar());
  12.         sqlCon.Close();
  13.         return readedIdValue;
  14.      }
  15.      catch
  16.      {
  17.         return -1;
  18.      }
  19. }

Wyszukiwanie osoby w bazie danych na podstawie imienia i nazwiska:

  1. public static byte searchInDBBaseOnNameAndSurname(string name, string surname)
  2. {
  3.     byte readedRows = 0;
  4.     try
  5.     {
  6.         sqlCon = new SqlConnection(sql.sqlConectionInfo.prepareConString());
  7.         sqlCon.Open();
  8.         string commandToExecute = String.Format(sql.sqlCardsComm.findPersonBaseOnNameOrSurname, name, surname);
  9.         SqlCommand myCommand = new SqlCommand(commandToExecute, sqlCon);
  10.         SqlDataReader myReader = myCommand.ExecuteReader();
  11.         while (myReader.Read())
  12.         {
  13.             readedRows++;
  14.         }
  15.         sqlCon.Close();
  16.     }
  17.     catch
  18.     {
  19.         return 0;  
  20.     }
  21.     return readedRows;
  22. }