C# 알아가기 (1. 간단한 학생 관리 폼)

min seung moon·2021년 8월 3일
0

C#알아가기

목록 보기
1/10
post-custom-banner

github : https://github.com/minseung-moon/student

1. 원폼 학생관리

  • 첫 직장으로 C# 개발 회사에 취업을 하였습니다. 하지만 왠걸 저는 C#이 처음이다 보니 부랴부랴 공부를 시작했고 C#을 어느정도 아는지 궁금하셔서 학생관리 폼을 만들어 보라고 하셔서 만들게 되었습니다

01. DB

-1. DB 설계

  • DB : MS SQL(SQL Server)
  • DB : STUDENT
  • TABLE : STUDENT
    • idx는 인덱스 번호로 PK와 IDENTITY를 주었다
    • name은 한글입력 및 공백을 안 받기 위해서 nvarchar로 지정

-2. PROCEDURE

  • Student_s1
USE [student]
GO
/****** Object:  StoredProcedure [dbo].[sp_Student_s1]    Script Date: 2021-08-03 오후 12:10:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.07. 19>
-- Description:	<학생 조회>
-- =============================================
ALTER PROCEDURE [dbo].[Student_s1]
AS
Begin

	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	SELECT *, 
		(kor + eng + math) AS total,
		CONVERT(NUMERIC(12,2) ,(kor + eng + math)/3.0) AS average,
		(SELECT COUNT(*) + 1 FROM student s2 WHERE (s2.kor + s2.eng + s2.math) > (s1.kor + s1.eng + s1.math)) AS Rank,
		
		CASE
			WHEN (kor < 40 OR eng < 40 OR math < 40 OR (kor + eng + math)/3 < 70) THEN '불합격'
			ELSE '합격'
		END AS "결과"
FROM student s1 ORDER BY idx ASC;
End
  • Student_i1
USE [student]
GO
/****** Object:  StoredProcedure [dbo].[sp_Student_i1]    Script Date: 2021-08-03 오후 1:02:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.07. 19>
-- Description:	<학생 입력>
-- =============================================
ALTER PROCEDURE [dbo].[Student_i1]
	@Name NVARCHAR(10),
	@Kor INT,
	@Eng INT,
	@Math INT
AS
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	INSERT INTO student(name, kor, eng, math) Values(@Name, @Kor, @Eng, @Math);
  • Student_u1
USE [student]
GO
/****** Object:  StoredProcedure [dbo].[Student_u1]    Script Date: 2021-08-03 오후 1:03:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.07. 19>
-- Description:	<학생 수정>
-- =============================================
ALTER PROCEDURE [dbo].[sp_Student_u1]
	@Name char(10),
	@Kor int,
	@Eng int,
	@Math int,
	@Idx int
AS
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	UPDATE student SET name = @Name, kor = @kor, eng = @eng, math = @math WHERE idx = @Idx;
  • Student_d1
USE [student]
GO
/****** Object:  StoredProcedure [dbo].[Student_d1]    Script Date: 2021-08-03 오후 1:04:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<문민승>
-- Create date: <2021.07. 19>
-- Description:	<학생 삭제>
-- =============================================
ALTER PROCEDURE [dbo].[sp_Student_d1]
	@Idx int
AS
	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

	DELETE FROM student WHERE idx = @Idx;

02. 코드

-01. Form1.cs

using static student.Conn.DBConn;
using student.Model;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using student.Repository;
using System.Text.RegularExpressions;

namespace student
{
    
    public partial class Form1 : Form
    {
        private IStudentRepository repository = null;
        private StudentRepositoryExcel excel = null;
        private List<StudentModel> studentList;
        private int index = -1;
        private string name = null;
        private string kor = null;
        private string eng = null;
        private string math = null;
        

        // 접속
        public Form1()
        {
            InitializeComponent();

            repository = new StudentRepository();
            excel = new StudentRepositoryExcel();
        }

        // form 로드 이벤트
        private void Form1_Load(object sender, EventArgs e)
        {
            ShowList();
        }

        // 추가 이벤트
        private void button1_Click(object sender, EventArgs e)
        {
            // text box에 데이터 확인
            if(TextBoxValidate())
            {
                MessageBox.Show("데이터를 입력해주세요");
                return;
            }
            repository.Add(new StudentModel { _Idx = index, _Name = name, _Kor = Convert.ToInt32(kor), _Eng = Convert.ToInt32(eng), _Math = Convert.ToInt32(math) });

            // 초기화
            InitTextBox();
            ShowList();
        }

        // 삭제 이벤트
        private void Delete_Click(object sender, EventArgs e)
        {
            // 그리드 뷰 컬럼이 선택이 되었는지 확인
            if (index > -1)
            {
                repository.DeleteByIdx(index);

                InitTextBox();
                ShowList();
            }else MessageBox.Show("삭제할 데이터를 입력해주세요.");
            
        }
        
        // 업데이트 이벤트
        private void Update_Click(object sender, EventArgs e)
        {
            // 그리드 뷰 컬럼이 선택이 되었는지 확인
            if (index > -1)
            {
                // text box 데이터 확인
                if (TextBoxValidate())
                {
                    MessageBox.Show("데이터를 정확하게 입력해주세요");
                    return;
                }

                repository.UpdateByIdx(new StudentModel { _Idx = index, _Name = name, _Kor = Convert.ToInt32(kor), _Eng = Convert.ToInt32(eng), _Math = Convert.ToInt32(math) });

                InitTextBox();
                ShowList();
            }
            else MessageBox.Show("수정할 데이터를 정확하게 입력해주세요.");
        }

        // 그리드 뷰 클릭 이벤트
        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) => SelectRows();

        // 선택된 컬럼의 데이터 할당
        private void SelectRows()
        {
            try
            {
                DataGridViewRow dr = dataGridView1.SelectedRows[0];
                index = (int)dr.Cells[0].Value;
                tbname.Text = dr.Cells[1].Value.ToString();
                tbkor.Text = dr.Cells[2].Value.ToString();
                tbeng.Text = dr.Cells[3].Value.ToString();
                tbmath.Text = dr.Cells[4].Value.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        // 텍스트 박스 초기화
        private void InitTextBox()
        {
            tbname.Text = "";
            tbkor.Text = "";
            tbeng.Text = "";
            tbmath.Text = "";
            index = -1;
        }

        // 텍스트박스에 값이 있는지 체크
        private bool TextBoxValidate()
        {
            name = tbname.Text;
            kor = tbkor.Text;
            eng = tbeng.Text;
            math = tbmath.Text;

            if(!Regex.IsMatch(name, @"^[가-힣]{2,10}$"))
            {
                tbname.Focus();
                return true;
            }
            if (!Regex.IsMatch(kor, @"^[0-9]{1,3}$") || (Convert.ToInt32(kor) < 0 || Convert.ToInt32(kor) > 100))
            {
                tbkor.Focus();
                return true;
            }
            if(!Regex.IsMatch(eng, @"^[0-9]{1,3}$") || (Convert.ToInt32(eng) < 0 || Convert.ToInt32(eng) > 100))
            {
                tbeng.Focus();
                return true;
            }
            if (!Regex.IsMatch(math, @"^[0-9]{1,3}$") || (Convert.ToInt32(math) < 0 || Convert.ToInt32(math) > 100))
            {
                tbmath.Focus();
                return true;
            }

            return false;
        }

        // 그리드 뷰에 데이터 출력
        private void ShowList()
        {
            // List 초기화
            studentList = new List<StudentModel>();

            studentList = repository.GetAll();
            dataGridView1.DataSource = studentList;
            dataGridView1.Columns[0].HeaderText = "번호";
            dataGridView1.Columns[1].HeaderText = "성명";
            dataGridView1.Columns[2].HeaderText = "국어";
            dataGridView1.Columns[3].HeaderText = "영어";
            dataGridView1.Columns[4].HeaderText = "수학";
            dataGridView1.Columns[5].HeaderText = "총합";
            dataGridView1.Columns[6].HeaderText = "평균";
            dataGridView1.Columns[7].HeaderText = "등수";
            dataGridView1.Columns[8].HeaderText = "결과";
        }

        // 엑셀 저장 이벤트
        private void button1_Click_1(object sender, EventArgs e)
        {
            excel.saveExcelFile();
        }

        // 프로그램 종료 이벤트
        private void End_Click(object sender, EventArgs e)
        {
            if(MessageBox.Show("종료하시겠습니까?", "종료", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                Application.Exit();
            }
            
        }
    }
}

-2. Conn

  • DB 연결
using System.Data.SqlClient;

namespace student.Conn
{
    class DBConn
    {
        private static string uid = null; // DB 접속 아이디
        private static string password = null; // DB 접속 비밀번호
        private static string database = null;  // 사용할 DB 이름
        private static string server = null;  // 서버 주소 -- sql 서버 접속시 사용한 주소
        private static SqlConnection conn = null;

        public static SqlConnection getConn()
        {
            uid = "";
            password = "";
            database = "";
            server = "";


            string connStr = $"SERVER = {server}; DATABASE = {database}; UID = {uid}; PASSWORD = {password};";
            

            conn = new SqlConnection(connStr);

            return conn;
        }

    }
}

-3. Repository

  • Controller 역할
  • IStudentRepository.cs
using student.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace student.Repository
{
    interface IStudentRepository
    {
        void Add(StudentModel model); // 입력
        List<StudentModel> GetAll(); // 전체 출력
        void DeleteByIdx(int index);  // 특정 학생 삭제
        void UpdateByIdx(StudentModel model); // 특정 학생 업데이트
    }
}
  • StudentRepository.cs
using student.Model;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static student.Conn.DBConn;

namespace student.Repository
{
    class StudentRepository : IStudentRepository
    {
        private static List<StudentModel> studentList = null;
        private SqlConnection conn = null;
        private SqlCommand cmd = null;

        public StudentRepository()
        {
            // DB 연동
            conn = getConn();
            cmd = new SqlCommand();
            cmd.Connection = conn;
        }

        public void Add(StudentModel model)
        {
            string sql = $"EXEC sp_Student_i1 '{model._Name}', {model._Kor}, {model._Eng}, {model._Math}";
            cmd.CommandText = sql;
            conn.Open();
            cmd.ExecuteNonQuery();

            // Db 닫기
            conn.Close();
        }

        public void DeleteByIdx(int index)
        {
            string sql = $"EXEC sp_Student_d1 {index}";
            cmd.CommandText = sql;
            conn.Open();
            cmd.ExecuteNonQuery();

            conn.Close();
        }

        // 데이터 조회
        public List<StudentModel> GetAll()
        {
            studentList = new List<StudentModel>();

            string sql = "EXEC sp_Student_s1";
            cmd.CommandText = sql;
            conn.Open();

            // 데이터 출력
            using (SqlDataReader SR = cmd.ExecuteReader())
            {
                while (SR.Read())
                {
                    StudentModel model = new StudentModel { _Idx = (int)SR[0], _Name = (string)SR[1], _Kor = (int)SR[2], _Eng = (int)SR[3], _Math = (int)SR[4], _Total = (int)SR[5], _Average = Convert.ToDouble(SR[6]), _Rank = (int)SR[7], _Result = (string)SR[8] };
                    // model._Result = (model._Average < 70.0 || model._Kor < 40 || model._Eng < 40 || model._Math < 40) ? "불합격" : "합격";
                    studentList.Add(model);
                }
                SR.Close();
            }
            conn.Close();

            return studentList;
        }

        public void UpdateByIdx(StudentModel model)
        {
            string sql = $"EXEC sp_Student_u1 '{model._Name}', {model._Kor}, {model._Eng}, {model._Math}, {model._Idx}";
            cmd.CommandText = sql;
            conn.Open();
            cmd.ExecuteNonQuery();

            conn.Close();
        }
    }
}
  • StudentRepositoryExcel.cs
using student.Model;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;

namespace student.Repository
{
    class StudentRepositoryExcel : IStudentRepository
    {
        private Excel.Application excelApp = null;
        private Excel.Workbook workBook = null;
        private Excel.Worksheet workSheet = null;
        private string desktopPath = null;
        private string path = null;

        private IStudentRepository repository = null;
        private List<StudentModel> studentList;

        public StudentRepositoryExcel()
        {
            desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // 바탕화면
            path = Path.Combine(desktopPath, "Excel.xlsx"); // 엑셀파일

            repository = new StudentRepository();
        }

        public void saveExcelFile()
        {
            try { 
                excelApp = new Excel.Application(); // 엑셀 어플리케이션 생성
                workBook = excelApp.Workbooks.Add(); // 워크북 추가
                workSheet = workBook.Worksheets.get_Item(1) as Excel.Worksheet; // 엑셀 첫번째 워크시트 가져오기

                workSheet.Cells[1, 1] = "학생 번호";
                workSheet.Cells[1, 2] = "학생 성명";
                workSheet.Cells[1, 3] = "국어점수";
                workSheet.Cells[1, 4] = "영어점수";
                workSheet.Cells[1, 5] = "수학점수";
                workSheet.Cells[1, 6] = "총합점수";
                workSheet.Cells[1, 7] = "평균점수";
                workSheet.Cells[1, 8] = "등수";

                // 엑셀에 저장할 데이터
                studentList = repository.GetAll();

                for(int i = 0; i < studentList.Count(); i++)
                {
                    workSheet.Cells[2 + i, 1] = studentList[i]._Idx;
                    workSheet.Cells[2 + i, 2] = studentList[i]._Name;
                    workSheet.Cells[2 + i, 3] = studentList[i]._Kor;
                    workSheet.Cells[2 + i, 4] = studentList[i]._Eng;
                    workSheet.Cells[2 + i, 5] = studentList[i]._Math;
                    workSheet.Cells[2 + i, 6] = studentList[i]._Total;
                    workSheet.Cells[2 + i, 7] = studentList[i]._Average;
                    workSheet.Cells[2 + i, 8] = studentList[i]._Rank;
                }

                workSheet.Columns.AutoFit(); // 열 너비 자동 맞춤
                workBook.SaveAs(path, Excel.XlFileFormat.xlWorkbookDefault); // 엑셀 파일 저장
                excelApp.Quit();
            }catch(Exception e)
            {
            }
            finally
            {
                ReleaseObject(workSheet);
                ReleaseObject(workBook);
                ReleaseObject(excelApp);
            }

        }
        
        private void ReleaseObject(object obj)
        { 
            try { 
                if(obj != null) 
                { 
                    Marshal.ReleaseComObject(obj); // 액셀 객체 해제 
                    obj = null;
                }
            } catch(Exception ex) 
            {
                obj = null; throw ex; 
            } finally 
            {
                GC.Collect(); // 가비지 수집 
            }
        }
        

        public void Add(StudentModel model)
        {
            throw new NotImplementedException();
        }

        public void DeleteByIdx(int index)
        {
            throw new NotImplementedException();
        }

        public List<StudentModel> GetAll()
        {
            throw new NotImplementedException();
        }

        public void UpdateByIdx(StudentModel model)
        {
            throw new NotImplementedException();
        }
    }
}

-4. Model

  • data model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace student.Model
{
    class StudentModel
    {
        private int idx; // 학생 번호
        private string name;  // 학생 성명
        private int kor;  // 국어 점수
        private int eng;  // 영어 점수
        private int math;  // 수학 점수

        private int total; // 합계
        private double average;  // 평균
        private int rank;  // 순위
        private string result;  // 결과(합격, 불합격)

        public int _Idx { get { return idx; } set { idx = value; } }
        public string _Name { get { return name; } set { name = value; } }
        public int _Kor { get { return kor; } set { kor = value; } }
        public int _Eng { get { return eng; } set { eng = value; } }
        public int _Math { get { return math; } set { math = value;  } }
        
        public int _Total { get { return total; } set { total = value; } }
        public double _Average { get { return average; } set { average = value; } }
        public int _Rank { get { return rank; } set { rank = value; } }
        public string _Result { get { return result; } set { result = value; } }
    }
}

03. 느낀 점

  • 처음으로 윈폼을 만지는 부분이 있어 많이 헤맸지만 자바보다는 수월했던것 같다
  • 이번에 처음으로 프로시저를 만들어서 사용하다 보니 어색한 점은 많지만 확실히 익혀놓으면 많은 도움이 될것 같다
    • 지금은 간단한 query지만 나중에 복잡해지면 프로시져는 필수일것 같은 느낌이 든다
profile
아직까지는 코린이!
post-custom-banner

0개의 댓글