728x90

C# 과 MySQL 연동방법에 대한 설명을 적어본다.

지금은 이런 연동방법을 고민할 필요는 없지만 최근에 네이버 지식인을 보다보니 질의로 올라오는 내용이 많아서 적어본다.


1. 개념 이해

2. phpMyAdmin 상에서 DB 생성 및 테이블 생성

3. C#과 MySQL 연동

이런 순서로 이해를 해야 한다.


1. 개념 이해

    - DB 와 연동하는 방식은 직접 연동방식과 간접 연동방식이 있다.

    - 직접 연동방식 : 연동을 위한 Driver 를 설치해야 한다.

                              http://link2me.tistory.com/758 참조하여 설치

    - 간접 연동방식 : 보안문제를 고려하여 Web 접속 방식으로 연동


2. phpMyAdmin 상에서 DB 생성 및 테이블 생성

    - 먼저 내 PC에 AutoSet9 을 설치하여 APM(Apache + PHP + MySQL) 환경을 만든다.

      http://link2me.tistory.com/797 참조

    - phpMyAdmin 접속을 한다.

      Web 브라우저에서 http://localhost 입력     



DB를 생성하고 나서 SQL 문을 복사하여 붙여넣기를 하면 테이블이 생성되고 샘플 데이터가 추가된다.



테이블 구조는

CREATE TABLE IF NOT EXISTS items (
  uid int(11) NOT NULL AUTO_INCREMENT,
  ItemName varchar(100) NOT NULL,
  Price double NOT NULL,
  Quantity int(11) NOT NULL,
  d_regis datetime NOT NULL,
  PRIMARY KEY (uid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;


로 만들었다.


3. C# 에서 MySQL 연결

    - MySQL root 패스워드를 통한 연동은 매우 위험하다.

      따라서 해당 DB만 접속할 수 있는 User 및 권한을 부여해야 한다.

      http://link2me.tistory.com/431 참조

   - 샘플 사용자용으로 csharp_user 란 user 를 추가해보자.

     GRANT ALL PRIVILEGES ON csharp.items TO csharp_user@localhost IDENTIFIED BY 'csharp1234';

     GRANT ALL PRIVILEGES ON csharp.items TO csharp_user@'%' IDENTIFIED BY 'csharp1234';



이제 CsharpMySqlSample 소스를 실행하여

app.config 를 수정한다.


그리고 compile을 하면 접속이 성공됨을 확인할 수 있다.


본 소스는 허접하게 접속이 된다는 것만 보여주는 소스 수준이라고 보면 된다.

MySQL.zip


접속 성공하신 분은 공감이나 댓글 달아주세요.

지금 이런 내용을 정리할 시간은 없는데 MySQL 연동 성공이 일단되어야 내용을 이해하고 수정하고 응용하면서 실력을 키워 나갈 수 있기 때문에 허접한 수준이지만 올렸습니다.

사실 2015년도 C# 배울 당시에 연습했던 파일을 찾아서 테스트 해보고 올리는 겁니다.



'C# > C# SQL' 카테고리의 다른 글

C# MySQL 엑셀로 내보내기  (0) 2016.08.28
C# MySQL Update  (0) 2016.08.22
C# dataGridView CSV 파일로 저장  (0) 2016.01.29
C# MySqlDataReader Format  (0) 2016.01.28
C# SQLite 데이터 삭제 (transaction 반영)  (0) 2016.01.14
블로그 이미지

Link2Me

,
728x90

http://link2me.tistory.com/822  에 설명된 자료를 보면 되는데 이 코드는 MySQL DB 에 있는 데이터를 내보내기 하는 코드이다.

속도가 느려서 추천하고 싶은 코드는 아니지만 필요할 때가 있을 때 인터넷 검색하고 코드가 맞는지 테스트하고 싶지 않아서 적어둔다.


using Excel = Microsoft.Office.Interop.Excel;


private void ExportToExcelFromMySQL(string fileName, DataGridView dgv, bool elapsedtime)
{
    Excel.Application excelApp = new Excel.Application();
    if (excelApp == null)
    {
        MessageBox.Show("엑셀이 설치되지 않았습니다");
        return;
    }
    Excel.Workbook wb = excelApp.Workbooks.Add(true);
    Excel._Worksheet workSheet = wb.Worksheets.get_Item(1) as Excel._Worksheet;

    try
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();  //동작시간 체크
        if (elapsedtime == true)
        {
            sw.Start();
        }

        using (var myConn = new MySqlConnection(GetConnectionString()))
        {
            myConn.Open();
            string strqry = "SELECT uid,eng,direct,is_direct,kor,(select classname from category where uid = data.category1) as cate1,(select classname from category where uid = data.category2) as cate2 ";
            strqry += "FROM data ";
            strqry += "where hidden=1 ";
            strqry += "ORDER BY uid DESC";
            using (var cmd = new MySqlCommand(strqry, myConn))
            {
                using (MySqlDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        int r = 0;
                        while (reader.Read())
                        {
                             파일로 저장할 정보 기록
                            csvExport.Write(reader.GetString(0)); csvExport.Write(delimiter);
                            workSheet.Cells[r + 2, 1] = reader.GetString(0);
                            workSheet.Cells[r + 2, 2] = reader.GetString(1);
                            workSheet.Cells[r + 2, 3] = reader.GetString(2);
                            workSheet.Cells[r + 2, 4] = reader.GetString(3);
                            workSheet.Cells[r + 2, 5] = reader.GetString(4);
                            workSheet.Cells[r + 2, 6] = reader.GetString(5);
                            workSheet.Cells[r + 2, 7] = reader.GetString(6);
                            r++;
                        }
                    }
                    else
                    {
                        MessageBox.Show("데이터가 없습니다");
                    }
                }
            }
            myConn.Close();
        }

         // 엑셀 2003 으로만 저장이 됨
        wb.SaveAs(fileName, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

        wb.Close(Type.Missing, Type.Missing, Type.Missing);
        excelApp.Quit();
        releaseObject(excelApp);
        releaseObject(workSheet);
        releaseObject(wb);

        if (elapsedtime == true)
        {
            sw.Stop();
            MessageBox.Show("소요시간 : " + sw.Elapsed.ToString() + " 이고 엑셀파일 저장완료");
        }
        else
        {
            MessageBox.Show("CSV 파일이 저장되었습니다");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;   비정상적인 상황(예외)이 발생한 경우 이를 알리는 데 사용
    }
}

#region 메모리해제
private static void releaseObject(object obj)
{
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        obj = null;
    }
    catch (Exception ex)
    {
        obj = null;
        throw ex;
    }
    finally
    {
        GC.Collect();
    }
}

#endregion


'C# > C# SQL' 카테고리의 다른 글

입문자를 위한 C# 과 MySQL 연동 방법 설명  (1) 2016.11.24
C# MySQL Update  (0) 2016.08.22
C# dataGridView CSV 파일로 저장  (0) 2016.01.29
C# MySqlDataReader Format  (0) 2016.01.28
C# SQLite 데이터 삭제 (transaction 반영)  (0) 2016.01.14
블로그 이미지

Link2Me

,

C# MySQL Update

C#/C# SQL 2016. 8. 22. 06:42
728x90

dataGridView 에서 작업한 것을 수정한 결과를 Update 하는 코드이다.

여러개의 자료를 수정한 경우 신규 수정인지 기존 자료 수정인지 검사하는 로직이 구현되어 있다.


private void btnSave_Click(object sender, EventArgs e)
{
    int UpdateCnt = 0; int ModifiedCnt = 0;

    myConn = new MySqlConnection(GetConnectionString());
    if (myConn.State == ConnectionState.Closed)
    {
        myConn.Open();
        DBstatus.Text = "ON";
    }

    try
    {
        foreach (DataGridViewRow row in this.dataGridView1.Rows)
        {
            string uid = row.Cells["uid"].Value.ToString();
            string str1 = row.Cells["content"].Value.ToString();
            string str2 = row.Cells["code"].Value.ToString();
            string d_regis = DateTime.Now.ToString("yyyyMMddHHmmss");

            if (str1 == null || str1.Equals("")) { continue; }  // 수정이 없을 경우
            else if (str2 == Convert.ToString(0))  // 신규 수정
            {
                string strqry = "UPDATE data SET code='" + f2.getCode + "', content='" + str1.Trim() + "', d_modify='" + d_regis + "' Where uid =" + uid;
                MySqlCommand cmd = new MySqlCommand(strqry, myConn);
                cmd.ExecuteNonQuery();
                UpdateCnt++;
                cmd.Dispose();
            }
            else if (str2 == Convert.ToString(f2.getCode))  // 등록자와 동일한 것만 수정여부 검사
            {                       
                string strqry = string.Format("SELECT count(*) FROM data WHERE uid='{0}' and content='{1}'",uid, str1);
                MySqlCommand cmd = new MySqlCommand(strqry, myConn);
                cmd.CommandType = CommandType.Text;
                int RowCount = Convert.ToInt32(cmd.ExecuteScalar());
                cmd.Dispose();
                if (RowCount == 0)
                {
                    strqry = "UPDATE data SET code='" + f2.getCode + "', content='" + str1.Trim() + "', d_modify='" + d_regis + "' Where uid =" + uid;
                    MySqlCommand cmb = new MySqlCommand(strqry, myConn);
                    cmb.ExecuteNonQuery();
                    ModifiedCnt++;
                    cmb.Dispose();
                }
            }
        }
        GetAllItems();  //Refresh grid
        MessageBox.Show(UpdateCnt + "건 Updated " + ModifiedCnt + "건 수정 되었습니다...");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if (myConn.State == ConnectionState.Open)
        {
            myConn.Close();
            DBstatus.Text = "OFF";
        }
    }

}



블로그 이미지

Link2Me

,
728x90

엑셀 내보내기가 속도가 너무 느리다는 답변을 보고 다시 테스트를 해봤다.

4만개의 데이터를 CSV 로 내보내기하는데 2초가 걸리지 않았다.

엑셀 내보내기를 했더니 무려 11분 12초가 걸렸다.

엑셀 내보내기 로직은 더 좋은 로직을 찾아보고 구현해야 할 거 같다.

PHP 에서 내보내기 테스트를 해봤을 때도 for 문 특히 2중 for 문을 사용하면 속도가 매우 느렸다.

하지만 while 문을 사용하면 속도가 엄청 빨랐다.


private void Save_ExportToCSVFile(string fileName, DataGridView dgv, bool elapsedtime)
{
    string delimiter = ";";  // 구분자
    FileStream fs = new FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
    StreamWriter csvExport = new StreamWriter(fs, System.Text.Encoding.UTF8);

    try
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); // 동작시간 체크
        if (elapsedtime == true)
        {
            sw.Start();
        }

        using (var myConn = new MySqlConnection(ConnectionString))
        {
            myConn.Open();
            string strqry = "select 칼럼명 from 테이블명 Where 조건문 ";
            using (var cmd = new MySqlCommand(strqry, myConn))
            {
                using (MySqlDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            // 파일로 저장할 정보 기록
                            csvExport.Write(reader.GetString(0)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(1)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(2)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(3));
                            csvExport.WriteLine();
                        }
                    }
                    else
                    {
                        MessageBox.Show("데이터가 없습니다");
                    }
                }
            }
            myConn.Close();
        }
        csvExport.Flush(); // flush from the buffers.
        csvExport.Close();
        fs.Close();

        if (elapsedtime == true)
        {
            sw.Stop();
            MessageBox.Show("소요시간 : " + sw.Elapsed.ToString() + " 이고 CSV 파일 저장완료");
        }
        else
        {
            MessageBox.Show("CSV 파일이 저장되었습니다");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;  // 비정상적인 상황(예외)이 발생한 경우 이를 알리는 데 사용
    }
}


'C# > C# SQL' 카테고리의 다른 글

C# MySQL 엑셀로 내보내기  (0) 2016.08.28
C# MySQL Update  (0) 2016.08.22
C# MySqlDataReader Format  (0) 2016.01.28
C# SQLite 데이터 삭제 (transaction 반영)  (0) 2016.01.14
C# SQLite dataGridView1 에 Select  (0) 2016.01.14
블로그 이미지

Link2Me

,
728x90

MySQL DB 데이터를 읽은 일반적인 포멧을 만들어 주고 사용하면 좋을거 같아서 포멧을 작성했다.

이 포멧은 SQLite, SQL, OleDB 등에서도 동일하게 사용 가능하다.

데이터를 읽어서 dataGridView, DataTable, listView 에 출력되도록 할 수도 있고

파일에 출력(저장)하게 할 수도 있다.


try
{
    using (var myConn = new MySqlConnection(ConnectionString))
    {
        myConn.Open();
        string strqry = "select 칼럼명 from 테이블명 Where 조건문 ";
        using (var cmd = new MySqlCommand(strqry, myConn))
        {
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {                            

                       reader.GetString(0);
                }

            }
        }
        myConn.Close();
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
    throw;  // 비정상적인 상황(예외)이 발생한 경우 이를 알리는 데 사용
}

블로그 이미지

Link2Me

,
728x90


C# SQLite 에서 다중으로 행을 선택한 경우 해당 행을 모두 삭제하는 코드이다.

C# SQLite에서 다량의 데이터를 삭제하는 테스트를 해봤더니 새벽에 테스트한 로직은 시간이 너무 많이 걸린다.

그래서 로직은 새로 구현하여 변경했고, 테스트 결과는 매우 만족스럽게 빠르게 처리된다.

foreach (DataGridViewRow item in this.dataGridView1.SelectedRows) 이 구문은 다중으로 행을 선택하면 로직이 가장 나중에 선택된 행부터 선택하여 삭제를 한다는 걸 확인했다.

연결형 방식으로 처리하며 코드는 아래 포멧을 준수하여 필요한 부분만 수정하면, 구글링이나 네이버 사이트 검색하지 않아도 될 것이다.

if (!this.dataGridView1.Rows[this.rowIndex].IsNewRow) 는 dataGridView 에서 신규행 추가를 위한 행이 아니면을 의미하므로 dataGridView 가 아닌 경우에는 코드를 제외하면 된다.

Update 처리도 동일한 방식으로 코드를 구현하면 된다.


private void btnDelete_Click(object sender, EventArgs e)
{
    int delete_cnt = 0; // 삭제건수 카운트
    if (!this.dataGridView1.Rows[this.rowIndex].IsNewRow)
    {
        using(var Conn = new SQLiteConnection(ConnectionString))
        {
            Conn.Open();
            using (var cmd = new SQLiteCommand(Conn))
            {
                using (var transaction = Conn.BeginTransaction())
                {
                    try
                    {
                        foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
                        {
                            cmd.CommandText = string.Format("DELETE FROM items Where uid={0}", item.Cells[2].Value);
                            cmd.ExecuteNonQuery();
                            delete_cnt++;
                        }
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        MessageBox.Show(ex.Message);
                        throw;
                    }
                }
            }
            Conn.Close();
            dgv = GetSqliteItems();
            MessageBox.Show(delete_cnt.ToString() + "건 삭제되었습니다...");
        }
    }
}

블로그 이미지

Link2Me

,
728x90

C# 에서 SQLite DB에 있는 테이블을 가져오는 쿼리문이며 dataGridView1 에 뿌려주는 코드이다.

dataGridView1_Display(ds.Tables[0]); 함수는 없어도 된다. dataGridView1 의 특정 칼럼을 readonly 로 한다든지, hidden 으로 처리할 칼럼을 지정한다든지 이런 화면 구성상의 옵션처리를 위해서 만든 함수이다.


string ConnectionString = @"Data Source=test.db;Version=3;";
SQLiteConnection sqliteConn;
SQLiteDataAdapter adapter;
DataTable dt;
DataTable GetSqliteItems()
{
    try
    {
        sqliteConn = new SQLiteConnection(ConnectionString);
        if (sqliteConn.State == ConnectionState.Closed)
        {
            sqliteConn.Open();
        }

        string strqry = "select * from items ";
        if (searchBox.Text.Length > 0)
        {
            strqry += "where Quantity='" + searchBox.Text + "' ";
        }
        strqry += "order by uid";
        adapter = new SQLiteDataAdapter(strqry, sqliteConn);  //
SQLiteDataAdapter 객체 생성

        DataSet ds = new DataSet();  // DataSet 객체 생성
        adapter.Fill(ds); // 생성된 DataSet ds에 데이터 채우기 : select * from items 의 결과물을 채우겠다.

        sqliteConn.Close();  // SQLite 연결해제
        dataGridView1.DataSource = ds.Tables[0];  //바인딩부분
        dataGridView1_Display(ds.Tables[0]); 
// 화면 구성/제어에 필요한 사용자 함수
         
        return ds.Tables[0];
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
    finally
    {
        //always close the connection
        if (sqliteConn.State == ConnectionState.Open)
        {
            sqliteConn.Close();
        }
    }
}


또다른 방법으로는


string ConnectionString = @"Data Source=test.db;Version=3;";

public void Read()
{
    try
    {
        using (var Conn = new SQLiteConnection(ConnectionString))
        {
            Conn.Open();
            string strqry = "select * from items ";
            if (searchBox.Text.Length > 0)
            {
                strqry += "where ItemName LIKE '%" + searchBox.Text + "%' or Price LIKE '%" + searchBox.Text + "%' or Quantity='" + searchBox.Text + "' ";
            }
            strqry += "order by uid";

            using (var cmd = new SQLiteCommand(strqry,Conn))
            {
                using(SQLiteDataReader reader = cmd.ExecuteReader())
                {
                    DataTable dataTable = new DataTable();
                    dataTable.Load(reader);
                    dataGridView1.DataSource = dataTable;
                    dataGridView1_Display(dataTable);  // 화면 구성/제어에 필요한 사용자 함수
                }
            }
            Conn.Close();
        }
           
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;
    }
}



블로그 이미지

Link2Me

,
728x90

C# SQLite 에서 다중으로 행을 선택한 경우 해당 행을 모두 삭제하는 코드이다.

this.dataGridView1.Rows[this.rowIndex].IsNewRow 은 dataGridVeiw1 에서 새로운 행 추가를 의미하므로 새로운 행 추가가 아닌 경우에만 행을 삭제할 수 있도록 if 문으로 처리했다.

SQLiteDataAdapter adapter;
DataTable ds;
변수 선언은 select 문에서 처리하면서 선언해서 delete 에서는 관련 내용이 나오지 않는다.


if (dataGridView1.SelectionMode != DataGridViewSelectionMode.FullRowSelect)
{
    dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
}

코드도 필요하면 추가해준다.


dataGridView1 자체의 행만 삭제하는 경우에는 아래 코드만 있으면 된다.

foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
{
    dataGridView1.Rows.RemoveAt(item.Index);
}
하지만 SQLite DB의 테이블 데이터까지 삭제하려면 아래 코드처럼 처리해줘야 한다.


private void btnDelete_Click(object sender, EventArgs e)
{
    if (!this.dataGridView1.Rows[this.rowIndex].IsNewRow)
    {
        sqliteConn = new SQLiteConnection(ConnectionString);
        sqliteConn.Open();

        foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
        {
            dataGridView1.Rows.RemoveAt(item.Index);
            // Set the DELETE command and parameter.
            adapter.DeleteCommand = new SQLiteCommand(
                "DELETE FROM items "
                + "WHERE uid=@uid;", sqliteConn);
            adapter.DeleteCommand.Parameters.Add("@uid", DbType.Int16, 4, "uid");
            adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
        }

        adapter.Update(ds);
        ds = GetSqliteItems();
        MessageBox.Show("선택한 행이 성공적으로 삭제되었습니다...");
    }
}

블로그 이미지

Link2Me

,
728x90

C# 에서 SQLite DB를 연동하려고 하니 Data Type 을 잘 몰라서 생소하다.

그래서 SQLite 로 DB를 변환해주는 툴(SQLiteConverter)을 이용하여 MySQL 테이블 구조와 데이터를 변환해봤다.

아래 테이블 구조는 구글링하다가 발견했던 자료(http://www.codeproject.com/Articles/71346/Connecting-to-MySQL-Database-using-C-and-NET)를 기준으로 기능 파악을 위해 이것저것 연습해보는 자료다.

이 자료가 100% 만족스런 결과를 가져다 주지는 못한다. 이 자료를 기반으로 응용해서 만들 때 Update, Insert 등을 해보면서 스스로 파악하면 된다.


MySQL 테이블 구조

CREATE TABLE IF NOT EXISTS items (
  uid int(11) NOT NULL AUTO_INCREMENT,
  ItemName varchar(100) NOT NULL,
  Price double NOT NULL,
  Quantity int(11) NOT NULL,
  d_regis datetime NOT NULL,
  PRIMARY KEY (uid)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


SQLite 테이블 구조

CREATE TABLE [items] (
'uid' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
'ItemName' TEXT NOT NULL,
'Price' REAL NOT NULL,
'Quantity' INTEGER NOT NULL,
'd_regis' DATETIME NOT NULL);

로 SQLite Expert 프로그램에서 확인할 수 있다.


보는 바와 같이 데이터타입(Data Type) 구조가 다르다.

http://www.sqlite.org/datatype3.html 에 가면 Data Type 구조에 대한 설명이 나온다.


NULL. The value is a NULL value.
INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
BLOB. The value is a blob of data, stored exactly as it was input.


SQLite 는 데이터베이스의 모든 정보가 하나의 파일에 저장된다.

테이블 스키마, 레코드 데이터, 인덱스와 같은 모든 정보가 한 파일에 저장된다.

파일 하나로 동작하기 때문에 다중 프로세스나 다중 스레드로 동작하는 경우 파일 잠금 이슈가 발생할 수 있다.

SQLite3 는 테이블 이름과 칼럼 이름에 대해 대소문자를 구별하지 않는다.

SQLite 는 동적 타이핑(dynamic typing)을 사용한다. 데이터 타입 제약을 강제하지 않는다.
어떤 데이터도 아무 컬럼에나 들어갈 수 있다.


대략적인 구조파악이 되었다면 이제 C# 과 SQLite 간에 연동을 위한 구조를 파악해야 한다.

SQLite Expert 에서 확인해보면 테이블 size 에 길이 제한이 없다.


아래 코드는 dataGridView1 에서 데이터를 Update, Insert 하는 코드인데, MySQL 기준으로 동작하던 걸 약간 수정해서 사용해보니 에러가 발생해서

adapter.UpdateCommand.Parameters.Add("@ItemName", DbType.String, 100, "ItemName");

와 같은 데이터 타입을 맞춰야 SQLite에 맞게 수정해야 한다.

http://www.blogbus.com/hyangl-logs/2219450.html 에 나온 SQLite ADO.NET wrapper 를 참조하여 적정하게 매핑처리하면 된다. 테이블의 사이즈가 없으니까 DbType.Int16 을 사용하던, DbType.Int32 를 사용하던 상관이 없을거 같다.

datetime 을 MySQL 에서는 now() 로 하면 되었지만, SQLite 에서는 에러가 발생한다.

datetime('now','localtime') 로 localtime 까지 해줘야만 한국시간으로 정확하게 표시가 된다.


private void btnSave_Click(object sender, EventArgs e)
{
    try
    {
        sqliteConn = new SQLiteConnection(ConnectionString);
        sqliteConn.Open();

        // Set the UPDATE command and parameters.
        adapter.UpdateCommand = new SQLiteCommand(
            "UPDATE items SET ItemName=@ItemName, Price=@Price, Quantity=@Quantity, d_regis=datetime('now','localtime') WHERE uid=@uid;", sqliteConn);
        adapter.UpdateCommand.Parameters.Add("@uid", DbType.Int16, 4, "uid");
        adapter.UpdateCommand.Parameters.Add("@ItemName", DbType.String, 100, "ItemName");
        adapter.UpdateCommand.Parameters.Add("@Price", DbType.Decimal, 10, "Price");
        adapter.UpdateCommand.Parameters.Add("@Quantity", DbType.Int16, 11, "Quantity");
        adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;

        // Set the INSERT command and parameter.
        adapter.InsertCommand = new SQLiteCommand(
            "INSERT INTO items VALUES (@uid,@ItemName,@Price,@Quantity,datetime('now','localtime'));",
            sqliteConn);
        adapter.InsertCommand.Parameters.Add("@uid", DbType.Int16, 4, "uid");
        adapter.InsertCommand.Parameters.Add("@ItemName", DbType.String, 100, "ItemName");
        adapter.InsertCommand.Parameters.Add("@Price", DbType.Decimal, 10, "Price");
        adapter.InsertCommand.Parameters.Add("@Quantity", DbType.Int16, 11, "Quantity");
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

        adapter.Update(ds);
        ds = GetSqliteAllItems();
        MessageBox.Show("성공적으로 저장되었습니다...");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}


MySQL 연동과 다르게 에러가 발생하는 부분이 좀 있어서 기능을 하나 하나 테스트하면서 수정해보고 있다.


SQLite 특징 및 분석 추천 사이트

http://crystalcube.co.kr/89

http://blog.naver.com/kai4th/20179602367

http://sqlite.org/faq.html#q1


블로그 이미지

Link2Me

,
728x90

SQLite DB를 생성하는 걸 연습해봤다.

SQLite 는 Data Type 이 MySQL 과는 다른 것 같아서 DB Type 부터 익혀야 할 것 같다.

SQLite DB는 PC에 설치하는 파일 DB 라서 파일명을 정해줘야 한다.

파일의 확장자는 sqlite 라고 하기도 하는데 편의상 dat 라고 정했다.

구글링으로 찾은 소스를 내가 사용하는 포멧 형태로 변경하고 파일 검사 루틴을 추가했다.

DB를 만들었는데 또 생성을 할 경우를 대비해서 try catch 문도 추가했으며,

테이블 생성시 테이블이 기존에 생성되어 있으면 생성하지 않도록 하는 CREATE TABLE IF NOT EXISTS 를 추가했다.

테이블을 이런식으로 만들지 않아서 그런지 참 생소하다.

빌드를 할 때 주의할 사항이 있다.

대상 플랫폼을 AnyCPU 로 설정했더니 에러가 발생했다.

 "여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 프로그램을 잘못된 형식으로 로드하려고 했습니다" 라는 에러 메시지가 팝업된다.

원인은 System.Data.SQLite 을 32비트 용으로 받았기 때문에 명확하게 32비트 환경에서 동작하도록 지정을 해줘야 한다.


==================== DB 생성 소스코드 =====================

using System.Data.SQLite;

private void sqliteDBCreate_Click(object sender, EventArgs e)
{
    string DbFile = "MyDatabase.dat";
    string ConnectionString = string.Format("Data Source={0};Version=3;", DbFile);
    try
    {
        if (!System.IO.File.Exists(DbFile))
        {
            SQLiteConnection.CreateFile(DbFile);  // SQLite DB 생성
        }
        else  // 기능 동작 여부 확인을 위해서 추가했지만 불필요
        {
            MessageBox.Show("DB 생성되어 있습니다");
            return;
        }


        // 테이블 생성 코드
        SQLiteConnection sqliteConn = new SQLiteConnection(ConnectionString);
        sqliteConn.Open();

        string strsql = "CREATE TABLE IF NOT EXISTS scores (name varchar(20), score int)";

        SQLiteCommand cmd = new SQLiteCommand(strsql, sqliteConn);
        cmd.ExecuteNonQuery();
        sqliteConn.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return;
    }
}


DB 의테이블을 조회(select), 추가(insert), 수정(update), 삭제(delete) 만 하고 테이블 생성은 SQL Expert Professional 을 가지고 해볼 생각이다.

일단 DB 구조부터 파악해야 하므로 처음부터 배운다는건 너무 어려울 거 같아서 찾아보니 http://www.sqlabs.com/sqliteconverter.php 가 있다. MySQL, Oracle 의 DB를 자동으로 변환해주는 툴이다.


직접 테스트를 해보니까 리눅스 서버에 있는 데이터베이스 접속해서 테이블 구조변환을 순식간에 한다.

이제 SQL Expert 를 이용하여 DB 을 열어서 내부 구조를 파악해 봐야겠다.

블로그 이미지

Link2Me

,
728x90

비주얼 스튜디오에서 참조를 찾아보니까 SQLite 는 기본으로 설정할 수가 없다.

따라서 SQLite 관련 DLL 을 구해야 한다.

http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki

에서 원하는 버전으로 다운로드 한다.


Setup 파일을 받아서 설치하면 Program Files(x86) 폴더에 설치된다.

설치된 곳을 찾아보면 DLL 파일 있다. 내가 설치한 DLL 파일이다.

.NET 4.0 32비트용 dll 파일 첨부 System.Data.SQLite.dll




코드 작성시 using System.Data.SQLite; 를 추가한다.


SQLite DB를 생성하는 것은 별도의 툴을 이용하는 것이 편하다.

http://www.sqliteexpert.com/download.html

에서 운영체제에 맞는 것을 받아서 설치하면 된다.


freeware 버전도 있는데 30일 trial 프로버전을 받아서  설치했다.

http://www.sqliteexpert.com/features.html 에 Personal 버전과 Professional 버전의 기능 차이가 나와 있고 가격도 표시되어 있다.


블로그 이미지

Link2Me

,
728x90

C# 에서 MySQL DB에 있는 자료를 DataSet 메모리 DB에 올린 다음 ListView 에 뿌리는 소스코드다.

listView 에 뿌려주는 순서를 정하려면

MySQL DB에서 Select 하는 구문에서 정해주면 된다.
select * from items 로 된 부분을 SELECT uid, item, price, Quantity, date FROM items 로 뽑아오고 싶은 칼럼만 지정하고 순서를 정하면 된다.


private void listView1Table()
{
    // listView1 의 검색 로직
    myConn = new MySqlConnection(ConnectionString);
    try
    {
        myConn.Open();

        string strqry = "select * from items ";
        if (listView1searchBox.Text.Trim().Length > 0)
        {
            strqry += "where Quantity='" + listView1searchBox.Text.Trim() + "' ";
        }
        strqry += "order by uid";

        adapter = new MySqlDataAdapter(strqry, myConn);
        DataSet ds = new DataSet();
        adapter.Fill(ds); // DS에 select * from items 의 결과물을 채우겠다.

        listView1.Items.Clear();
        DataTableTolistView(ds.Tables[0], listView1);

        lvt1totalcnt.Text = "총 " + i.ToString() + " Row";
        SetHeight(listView1, 20);  // 행높이 지정
        listView1.HeaderStyle = ColumnHeaderStyle.Nonclickable;
        myConn.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void DataTableTolistView(DataTable dtable, ListView LV)
{
    if (dtable.Rows.Count > 0)
    {
        int i = 0;
        foreach (DataRow drow in dtable.Rows)
        {
            i = i + 1;
            ListViewItem lvt = new ListViewItem();
            lvt.Text = i.ToString();  // 첫번째 칼럼에 저장, 첫번째 칼럼은 번호 증가 목적
            for (int n = 0; n < dtable.Columns.Count; n++)
            {
                lvt.SubItems.Add(drow[n].ToString());
            }
            LV.Items.Add(lvt);
        }
    }
}

블로그 이미지

Link2Me

,
728x90

C# comboBox 에 테이블명을 가져오는 걸 알고 싶다는 질문이 있어서 테이블명 가져오기를 해봤다.

이런 걸 하기 위한 첫번째 요건은 MySQL 검색어로 테이블명 찾는 명령어가 무엇인지부터 알아내는 것이다.

나머지는 C# 코드에 맞게 작성해서 화면에 뿌려주면 된다.

어떤 DB에 있는 테이블명을 알고 싶은지 적어주면 된다. Where 조건을 빼면 모든 테이블명 리스트가 검색된다.

단, MySQL 접속권한에 따라 모든 테이블 검색이 안될 수도 있다.


private void getTablecomboBox()
{
    comboBox1.Items.Clear();
    comboBox1.Items.Add("테이블명");
    try
    {
        myConn = new MySqlConnection(ConnectionString);
        myConn.Open();
        string strqry = "select table_name from information_schema.tables where TABLE_SCHEMA='DB명'";

        MySqlCommand cmd = new MySqlCommand(strqry, myConn);
        cmd.CommandType = CommandType.Text;
        MySqlDataReader R = cmd.ExecuteReader();

        if (R.HasRows)
        {
            while (R.Read())
            {
                comboBox1.Items.Add(R.GetString(0));
            }
        }
        else
        {
            MessageBox.Show("테이블이 하나도 없습니다");
        }
        R.Dispose();
        myConn.Close();

    } catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

블로그 이미지

Link2Me

,
728x90

C# listView 에서 편집하는 자료를 DB에 추가/수정/삭제하는 코드이다.

소스코드를 참조하면 내용 이해가 되리라 보며 설명은 생략한다.

좀 더 이해를 원하면 http://link2me.tistory.com/779 자료를 참조하면 된다.


private void listView_DBInsert()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "INSERT INTO items VALUES (@uid, @ItemName, @Price, @Quantity, @d_regis);";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters.Add("@ItemName", MySqlDbType.VarChar, 100);
    cmd.Parameters.Add("@Price", MySqlDbType.Decimal, 10);
    cmd.Parameters.Add("@Quantity", MySqlDbType.Int16, 11);
    cmd.Parameters.Add("@d_regis", MySqlDbType.DateTime); 

    cmd.Parameters["@uid"].Value = null;  // 값이 자동으로 증가하기 때문에 null 로 해주면 됨
    cmd.Parameters["@ItemName"].Value = ItemNameBox.Text;
    cmd.Parameters["@Price"].Value = PriceBox.Text;
    cmd.Parameters["@Quantity"].Value = QuantityBox.Text;
    cmd.Parameters["@d_regis"].Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

    cmd.ExecuteNonQuery();

    ItemNameBox.Text = "";
    PriceBox.Text = "";
    QuantityBox.Text = "";

    listView1Table();

    cmd.Dispose();
    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}

private void listView_DBSave()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "UPDATE items SET ItemName=@ItemName, Price=@Price, Quantity=@Quantity, d_regis=NOW() WHERE uid=@uid;";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters.Add("@ItemName", MySqlDbType.VarChar, 100);
    cmd.Parameters.Add("@Price", MySqlDbType.Decimal, 10);
    cmd.Parameters.Add("@Quantity", MySqlDbType.Int16, 11);

    cmd.Parameters["@uid"].Value = listView1.SelectedItems[0].SubItems[2].Text;
    cmd.Parameters["@ItemName"].Value = ItemNameBox.Text;
    cmd.Parameters["@Price"].Value = PriceBox.Text;
    cmd.Parameters["@Quantity"].Value = QuantityBox.Text;
    //cmd.Parameters["@d_modify"].Value = DateTime.Now.ToString("yyyyMMddHHmmss");

    cmd.ExecuteNonQuery();

    listView1Table();

    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}


private void listView_Delete()
{
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();

    string strqry = "DELETE FROM items WHERE uid = @uid;";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.Parameters.Add("@uid", MySqlDbType.Int16, 4);
    cmd.Parameters["@uid"].Value = listView1.SelectedItems[0].SubItems[2].Text;
    cmd.ExecuteNonQuery();

    // DB 테이블 자료를 삭제했으므로 화면상의 텍스트박스 내용 초기화
    ItemNameBox.Text = "";
    PriceBox.Text = "";
    QuantityBox.Text = "";

    listView1Table();

    if (myConn.State == ConnectionState.Open)
    {
        myConn.Close();
    }
}


블로그 이미지

Link2Me

,
728x90

C# 에서 MySQL 등 DB에 있는 자료를 ListView 에 가져오는 소스코드다.

읽어온 자료는 R.GetString(0) 부터 나온다.

가령 Select uid, id, name, email FROM 테이블명;

이라고 할 경우 R.GetString(0) 는 uid 칼럼이고, R.GetString(1) 은 id, R.GetString(2) 는 name, R.GetString(3) 은 email 칼럼이다.

listView 에 자료를 추가하는 것에 대해 이해하고자 하면 listView 기능 분석 게시글을 참조하면 도움된다.


private void listView1Table()
{
    myConn = new MySqlConnection(ConnectionString);
    try
    {
        myConn.Open();

        string strqry = "select * from items ";
        if (searchBox.Text.Trim().Length > 0)
        {
            strqry += "where Quantity='" + searchBox.Text.Trim() + "' ";
        }
        strqry += "order by uid";

        MySqlCommand cmd = new MySqlCommand(strqry, myConn);
        cmd.CommandType = CommandType.Text;
        MySqlDataReader R = cmd.ExecuteReader();

        listView1.Items.Clear();
        if (R.HasRows)
        {
            int i = 0;
            while (R.Read())
            {
                i = i + 1;
                ListViewItem lvt = new ListViewItem();
                lvt.SubItems.Add(i.ToString());
                lvt.SubItems.Add(R["uid"].ToString());
                lvt.SubItems.Add(R.GetString(1));
                lvt.SubItems.Add(R.GetString(2));
                lvt.SubItems.Add(R.GetString(3));
                lvt.SubItems.Add(R.GetString(4));
                listView1.Items.Add(lvt);
            }
            lvt1totalcnt.Text = "총 " + i.ToString() + " Row";
        }
        else
        {
            MessageBox.Show("데이터가 없습니다");
        }
        R.Close();
        SetHeight(listView1, 20);  // 행높이 지정 --> 사용자 정의 함수로 없어도 된다. 다른 게시글 참조하면 나옴
        listView1.HeaderStyle = ColumnHeaderStyle.Nonclickable;
        myConn.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }           
}




블로그 이미지

Link2Me

,

C# DataSet

C#/C# SQL 2015. 12. 20. 13:13
728x90

PC , 스마트폰(아이폰, 안드로이드폰) 상에서 사용하는 로컬 데이터베이스로는 SQLite 가 많이 사용된다.

SQLite 는 직접 다루게 될 때 정리를 해볼 생각이다.


DataSet 은 클라이언트 메모리 상의 데이터베이스다.


메모리상에 만드는 데이터베이스는 PC를 끄거나 프로그램을 종료하면 데이터가 날라가 버린다.

따라서, 실제 데이터베이스(오라클, MySQL, MS-SQL, SQLite, 엑셀, MS Access 등)에 있는 자료를 불러다가 DataSet 과 연결하여 작업을 하고 Update, Delete, Insert 를 수행하게 된다.

DataTable 클래스는 메모리상에 테이블을 표현하는 클래스이다.
DataSet(메모리 상의 데이터베이스)은 여러개의 DataTable 들을 포함한다.



일반적으로 SqlDataAdapter 를 이용하여 데이타를 서버로부터 가져와 메모리상의 DataSet에 할당 후 사용한다.

MySQL 과 연결하는 것은 앞에 My만 붙여준다고 이해하면 된다.


static string ConnectionString = string.Format("SERVER={0};DATABASE={1};UID={2};PASSWORD={3};",server_ip,dbname,username,password);  // 실제 연결할 DB의 정보를 입력해야 함
MySqlConnection myConn;
MySqlDataAdapter adapter;

myConn = new MySqlConnection(ConnectionString);
if (myConn.State == ConnectionState.Closed)
{
    myConn.Open();
}
string strqry ="SELECT * FROM Table_A";

strqry += " Where 조건문";

adapter = new MySqlDataAdapter(strqry, myConn);

DataSet ds = new DataSet(); // DataSet 객체에 메모리 할당
adapter.Fill(ds, "DSTables"); // DataSet에 테이블 데이타를 넣음


for 문, foreach 문, while 문을 활용하여 데이터를 콘솔화면에 출력하거나

dataGridView와 바인딩하여 dataGridView 화면에 출력한다.

또는 listView, TreeView 에 출력할 수도 있다.


if (myConn.State == ConnectionState.Open)
{
    MyConn.Close();
}


ds.Tables["DSTables"].Rows.Count 는 총 레코드수를 반환한다.

dataGridView1.DataSource = ds.Tables[0]; // DataSet을 DataGridView 컨트롤에 바인딩

ds.Tables[0].Rows.Count.ToString(); // DB에서 가져온 총 Record 수

DataTable dt = ds.Tables["DSTables"];


메모리상의 DB인 DataSet 과 실제 DB인 SQL 간에 SqlDataAdapter 를 이용하여 Select, Update, Insert, Delete 를 한다.

블로그 이미지

Link2Me

,
728x90

C# 에서 MySQL 에 접속하여 게시물 갯수를 구하는 간단한 코드이다.


먼저 상시적으로 사용되는 것은 Class 상위에 둔다.

C# 에서 MySQL 을 접속시 localhost 의미하는게 뭔지 모르는 개발 입문자들이 많은거 같다.

localhost = 서버와 클라이언트(C#으로 만든 프로그램)가 같은 곳에 존재

호스팅을 이용할 경우에는 클라이언트와 서버의 물리적인 장소가 서로 다르다. 이 경우에는 서버의 실제 접속 IP주소를 적어줘야 한다.


MySQL 에서는 외부에서 접속할 수 있는 사용자권한을 부여해야 한다. 이 사항은 http://link2me.tistory.com/431 게시글을 읽어보면 이해가 될 것이다.


이 두가지 사항을 알고 이제 코드를 작성해보자.


MySQL 접속하여 결과를 얻는 방법은 여러가지가 있다.

여기서는 Select count(*) FROM 테이블명 WHERE 조건; 인 단순 예제를 작성했다.

object result = cmd.ExecuteScalar();

ExecuteScalar() 메서드는 쿼리를 실행하고 쿼리에서 반환된 결과 집합의 첫번째 행의 첫번째 열을 반환한다.

추가 열이나 행은 무시한다. 집계함수(SUM, AVG, MAX, MIN) 를 이용한 결과를 구할 때 사용된다.

ConnectionString은 암호화를 하여 저장하고 실제 사용할 때만 복호화를 할 수 있으면 제일 좋다.


=== 소스코드 ===

string ConnectionString = "SERVER=localhost;DATABASE=dbname;UID=dbuserid;PASSWORD=dbpassword;";
MySqlConnection myConn;

private int totalcnt()
{
    int cnt = 0;
    try
    {
        myConn = new MySqlConnection(ConnectionString);
        if (myConn.State == ConnectionState.Closed)
        {
            myConn.Open();
        }
        string strqry = "select count(uid) from data";
        MySqlCommand cmd = new MySqlCommand(strqry, myConn);
        cnt = int.Parse(cmd.ExecuteScalar().ToString());
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.myConn.Close();
    }
    return cnt;
}


본 게시글은 MySQL 접속을 알고 싶은 초보자를 위해 작성해봤습니다.



'C# > C# SQL' 카테고리의 다른 글

C# MySQL 데이터를 ListView 에 Add 하는 방법 (1)  (2) 2015.12.29
C# DataSet  (6) 2015.12.20
C# MySQL 쿼리문과 연동 처리  (0) 2015.09.12
C# 콤보박스(comboBox) 와 SQL 연동  (0) 2015.09.10
C# 과 MySQL 연동  (0) 2015.08.29
블로그 이미지

Link2Me

,
728x90

C# 에서 MySQL 구문과 연동처리하는 부분에서 좀 고생을 해서 적어둔다.


MySQL 칼럼에 인덱스를 걸어야 속도가 빠르지만, 칼럼에 변형을 가해서 인덱스 무시하고 처리했다.

substring(d_modify,1,8)='" + DateTime.Now.ToString("yyyyMMdd") + "'


MySQL d_modify 칼럼은 변경된 날짜를 기록하는 칼럼인데 php 에서 값을 저장할 때 varchar(14) 로 날짜의 형식을 일반적인 php 날짜 형식과 약간 다르게 yyyyMMddHHmmss 로 저장된다.

연도,월,날짜,시,분,초를 구분자 없이 14자리를 저장한다.

오늘 날짜(년월일) yyyyMMdd 8자리만 MYSQL substring 함수를 이용하였다.

MySQL 칼럼은 string(문자열) 인 경우에는 d_modify ='값' 으로 처리한다.

여기에 C# 에서 입력되는 변수를 적용하려면 " + 입력값 + " 를 ' ' 사이에 넣어준다.


dataGridView 화면 내부에서 직접 자료를 갱신하는 경우가 아니라 외부의 값을 넣어야 하는 부분을 몰라 고생을 좀 했다.

content 칼럼을 업데이트하는 부분과 d_modify 칼럼을 업데이트하는 부분을 서로 다르게 처리한다.

[2] 와 같이 해주거나, ["@d_modify"] 해줘야 제대로 동작된다.

["d_modify"] 이런식으로 하면 에러가 발생한다.


// Set the UPDATE command and parameters.
d_modify_value = DateTime.Now.ToString("yyyyMMddHHmmss");
adapter.UpdateCommand = new MySqlCommand(
    "UPDATE data SET content=@content,d_modify=@d_modify WHERE uid=@uid;", myConn);
adapter.UpdateCommand.Parameters.Add("@uid", MySqlDbType.Int16, 11, "uid");
adapter.UpdateCommand.Parameters.Add("@content", MySqlDbType.VarChar, 255, "content");
adapter.UpdateCommand.Parameters.Add("@d_modify", MySqlDbType.VarChar, 14);
adapter.UpdateCommand.Parameters[2].Value = d_modify_value// 외부 값을 저장
adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;



'C# > C# SQL' 카테고리의 다른 글

C# DataSet  (6) 2015.12.20
C# MySQL 간단 코드 및 접속 기본지식 배우기  (0) 2015.12.04
C# 콤보박스(comboBox) 와 SQL 연동  (0) 2015.09.10
C# 과 MySQL 연동  (0) 2015.08.29
C# ExecuteScalar 와 총 Record 수  (0) 2015.08.27
블로그 이미지

Link2Me

,
728x90

콤보박스에 뿌려질 category 리스트를 MySQL 데이터베이스와 연동하는 방법을 해봤다.

정말 힘들게 겨우 구현에 성공했다.

comboBox에 뿌려질 리스트를 만드는 것은 어렵지 않다.

문제는 값을 선택했을 때, Event 가 발생하도록 연동처리하는 것을 아직 완벽하게 이해하지 못했다.

uid 값을 한번에 넘기는 방법이 있을거 같은데 ㅠㅠㅠ

C# 배운지 한달도 안되는데 이 정도 구현한 것만으로도 나자신을 대견하게 생각해야 하겠지.

무식하게 2단계로 나눠서 comboBox1을 선택하면 cat1name 을 받아서 cat1uid 를 다시 조회하는 Query 문을 만든다음에 data 테이블로 결과를 던져서 원하는 결과를 가져오는 로직으로 구현을 했다.


void cat1comboBox()
{
    comboBox1.Items.Clear();
    comboBox1.Items.Add("전체");
    try
    {
        myConn = new MySqlConnection(ConnectionString);
        myConn.Open();
        string strqry = "select uid, name from category where relateduid=0";
        strqry += " order by uid";
        adapter = new MySqlDataAdapter(strqry, myConn);
        DataSet cat1 = new DataSet();
        adapter.Fill(cat1);
        foreach (DataRow dr in cat1.Tables[0].Rows)
        {
            comboBox1.Items.Add(dr["name"]);
        }

        comboBox1.SelectedIndex = 0;  // 첫번째 아이템 선텍

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.myConn.Close();
    }
}

DataTable cat2comboBox(string category1)
{
    comboBox2.Items.Clear();
    comboBox2.Items.Add("전체");
    try
    {
        myConn = new MySqlConnection(ConnectionString);
        myConn.Open();
        string strqry = "select uid, name from category";
        strqry += " where relateduid=(select uid from category where relateduid=0 and name='" + category1 + "')";
        strqry += " order by uid";
        adapter = new MySqlDataAdapter(strqry, myConn);
        DataSet cat2 = new DataSet();
        adapter.Fill(cat2);
        foreach (DataRow dr in cat2.Tables[0].Rows)
        {
            comboBox2.Items.Add(dr["name"]);
        }
        return cat2.Tables[0];
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
    finally
    {
        this.myConn.Close();
    }
}


private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    cat2 = cat2comboBox(comboBox1.SelectedItem.ToString());
    cat1name = comboBox1.SelectedItem.ToString(); // data 테이블 검색어 전달

    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();
    string strqry = "select uid from category";
    strqry += " where relateduid=0 and name='" + cat1name + "' ";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.CommandType = CommandType.Text;
    MySqlDataReader dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        cat1uid = dr.GetString(0);
    }
    dr.Close();
    myConn.Close();
}

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
    cat2name = comboBox2.SelectedItem.ToString(); // data 테이블 검색어 전달
    myConn = new MySqlConnection(ConnectionString);
    myConn.Open();
    string strqry = "select uid from category";
    strqry += " where relateduid='" + cat1uid + "' and name='" + cat2name + "' ";
    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.CommandType = CommandType.Text;
    MySqlDataReader dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        cat2uid = dr.GetString(0);
    }
    dr.Close();
    myConn.Close();
}


-------------------------------------------------------------------------

함수를 더 정교하게 사용하는 방법은

comboBox1 부분을 CB 로 변경하는 것이다.

즉 comboBox CB 로 함수 인자를 만들어서 받으면 된다.



'C# > C# SQL' 카테고리의 다른 글

C# MySQL 간단 코드 및 접속 기본지식 배우기  (0) 2015.12.04
C# MySQL 쿼리문과 연동 처리  (0) 2015.09.12
C# 과 MySQL 연동  (0) 2015.08.29
C# ExecuteScalar 와 총 Record 수  (0) 2015.08.27
C# 과 MySQL 연결을 위한 준비  (0) 2015.08.05
블로그 이미지

Link2Me

,

C# 과 MySQL 연동

C#/C# SQL 2015. 8. 29. 00:30
728x90

책보고 네이버/구글 폭풍검색하다보니 좀 정리가 되는거 같다.

도식화된 그림은 구글 이미지 검색해서 찾았다.


C#에서 데이터베이스에 연결하는 방법은 세가지 방법이 있다.

ㅇ C# 과 DB 직접 접속방식 (기업 내부에 서버가 있는 경우)

   - 연결형으로 데이터베이스 사용하기

   - 비연결형으로 데이터베이스 사용하기

ㅇ C# 과 DB 간접 접속방식

   - C# - PHP(JSP, ASP) - DB (보안문제 해결)


아래 설명은 DB 직접 접속방식에 대한 설명이다.

SQL 연결방식은 SQL Server, MySQL, Oracle 등 모두 동일한 방식으로 제공하고 있다.

어떤 DB에 접속하는지 식별할 수 있게 하는 것만 다르다.



C# 과 MySQL 을 연동하기 위해서 가장 먼저 해야 할 일은 아래의 네임스페이스들을 참조해야 한다.

using System.Data;  // DB처리 관련된 일반 클래스

//Include mysql client namespace.
using MySql.Data.MySqlClient;
using System.Configuration;

* 연결하는 DB에 따라 참조하는 네임스페이스는 달라진다.


Mysql 데이터 연결
MySQL 데이타베이스를 연결하기 위해서는 MySqlConnection 클래스를 사용한다.

//Read connection string from application settings file (데이터베이스 연결)
string  ConnectionString = ConfigurationSettings.AppSettings["ConnectionString"];  // DB 연결 정보

MySqlConnection myConn// 보통 Conn 으로 표현되어 있고, AccessConn 은 액세스 연결, myConn 은 MySQL 연결
myConn = new MySqlConnection(ConnectionString);

MySQL 데이터를 C# 으로 가져오기 위해서는

MySqlCommand / MySqlDataReader (연결형 데이터베이스 사용)

또는 

MySqlCommand / MySqlDataAdapter (비연결형 데이터베이스 사용)

를 사용한다.



1. 연결형으로 데이터베이스 사용하기


MySqlCommand 는 모든 SQL 구문을 실행시켜 주는 담당 객체 (select, update, delete, insert, create, drop 등)

string sql = "select * from TableName where 조건";
MySqlCommand cmd = new MySqlCommand(sql, myConn);

MySqlDataReader는 연결모드로 데이터를 서버에서 가져온다.

Query 문에서 어떠한 값이 리턴 될지 모르기 때문에 Object형으로 반환된다.
따라서 반환값을 적절히 변환하여 사용해야 한다.
또한 Query의 결과 값이 여러 개의 행과 열을 가질 수 있는데, 이런 경우에는 첫 번째 행의 첫 번째 열의 값이 리턴된다.


ExecuteReader는 여러 개의 행과 열을 동시에 가져올 때 사용한다. 삽입, 삭제, 수정 등은 할 수 없다.

주로 Select 명령문을 실행하고 그 결과셋을 SqlDataReader 타입의 객체로 리턴한다.

string sql = "select * from items order by uid desc";
myConn.Open();  // mysql DB 연결
MySqlDataReader R = new MySqlCommand(sql, myConn).ExecuteReader();

* MySqlDataReader 는 record 단위로 접근하며, 하나의 reader 가 열려 있으면 또다른 reader는 열수가 없다.

while (R.Read())    // 칼럼을 배열처럼 사용하여 R[0]는 첫번째 칼럼,  R[1] 은 두번째칼럼
{   // R 은 한번에 하나의 레코드에만 접근 가능

    // R['uid'], R['name'] 으로 칼럼을 직접 명기할 수 있다.
    label1.text = R[0].ToString();  // string name = R.GetString(0);

    label2.text = R[1].ToString();
}
R.Close();   // 쿼리문 결과 닫기. reader 로 열였으면 반드시 닫아주어야 한다.
myConn.Close();  // mysql DB 연결 종료


ExecuteNonQuery는 결과를 받을 필요가 없는 Query문에 사용된다
보통 Insert문이나 Update문은 결과를 받을 필요가 없기 때문에, Insert, Update 문에서 많이 사용한다
위와 같은 Query에서는 몇 개행에 적용되었는지가 중요한데, ExecuteNonQuery는 적용된 행의 개수를 리턴해준다
string qry ="UPDATE items SET Quantity=10 WHERE uid='" + user_id +"'";
MySqlCommand cmd = new MySqlCommand(qry, myConn);
myConn.Open();
cmd.ExecuteNonQuery();
myConn.Close();

ExecuteScalar는 Query문에서 1개의 값을 가져올 때 사용한다.
결과가 딱 1개인 집계함수(count, sum, avg, max, min 등)에 사용한다.


2. 비연결형으로 데이터베이스 사용하기


비연결형의 핵심은 메모리에 구축된 DB인 DataSet 클래스이다. 메모리상의 오프라인 DB라고 할 수 있다.

SQL Server, Oracle, MySQL 같은 DBMS의 테이블은 물론이고 Excel Worksheet, XML 파일, 텍스트파일까지도 DataSet 에 넣어 놓고 관리할 수 있다. 단점은 대량의 데이터를 메모리에 계속 보유해야 하므로 Client(PC, 노트북)의 리소스를 엄청 소모할 수 있다.

MySqlDataReader는 연결모드로 데이터를 서버에서 가져오는 반면, (메모리 공간 별로 차지하지 않음)
MySqlDataAdapter는 한꺼번에 클라이언트 메모리로 데이터를 가져온 후 연결을 끊는다.

MySQL DB 와 연결이 끊어져 있어도 SQL 작업이 가능하다.

받은 전체 데이터(MySqlDataAdapter)는 주로 로컬에 있는 DataSet 객체 안에 메모리상의 테이블 형태로 존재하는데, 이를 각종 컨트롤들에게 바인딩 시킬 수 있다.


MySqlDataAdapter adapter;
string sql = "select * from items order by uid";
adapter = new MySqlDataAdapter(sql, myConn);
DataSet DS = new DataSet();
adapter.Fill(DS);

MySqlCommand 로 Update, Insert, Delete Query 문 처리하고

DS.Tables[0];


DataTable ds;

dataGridView1.DataSource = ds;  // DataSource 에 DataTable 객체를 대입하면 테이블이 표형식으로 출력


* 테이블의 실제 데이터를 저장하는 것은 Record(행)이며 행은 DataRow 클래스로 표현한다.


도움되었다고 생각되면 공감 꾸욱 눌러주세요.


블로그 이미지

Link2Me

,