40. [ADO.NET] DataTable과 XML, 도서 관리 프로그램

DataTable 클래스에서는 메모리 상의 테이블입니다. ADO.NET 에서는 논리적 DB를 XML 형태로 저장하고 로딩할 수 있게 기술을 지원하고 있습니다.

DataTable 클래스에도 WriteXml, WriteXmlSchema, LoadXml, LoadXmlSchema 메서드를 제공하여 메모리 상의 테이블 구조와 내용을 XML 형태로 저장하고 로딩할 수 있습니다.

public void WriteXml(Stream stream);

public void WriteXml(string filename);;

public void WriteXml(TextWriter writer);

public void WriteXml(XmlWriter writer);

public void WriteXml(Stream stream, bool hierarchy);

//hierarchy: 테이블의 모든 하위 항목 내용 포함 여부

public void WriteXml(Stream stream, XmlWriteMode mode);

public void WriteXml(string filename, bool hierarchy);

public void WriteXml(string filename, XmlWirteMode mode);

public void WriteXml(TextWriter writer, bool hierarchy);

public void WriteXml(TextWriter writer, XmlWirteMode mode);

public void WriteXml(XmlWriter writer, bool hierarchy);

public void WriteXml(XmlWriter writer, XmlWirteMode mode);

public void WriteXml(Stream stream, XmlWriteMode mode, bool hierarchy);

public void WriteXml(string filename, XmlWriteMode mode, bool hierarchy);

public void WriteXml(TextWriter writer, XmlWriteMode mode, bool hierarchy);

public void WriteXml(XmlWriter writer, XmlWriteMode mode, bool hierarchy);



public void WriteXmlSchema(Stream stream);

public void WriteXmlSchema(String filename);

public void WriteXmlSchema(TextWriter writer);

public void WriteXmlSchema(XmlWriter writer);

public void WriteXmlSchema(Stream stream, bool hierarchy);

public void WriteXmlSchema(String filename, bool hierarchy);

public void WriteXmlSchema(TextWriter writer, bool hierarchy);

public void WriteXmlSchema(XmlWriter writer, bool hierarchy);



public XmlReadMode ReadXml(Stream stream);

public XmlReadMode ReadXml(string filename);

public XmlReadMode ReadXml(TextWriter writer);

public XmlReadMode ReadXml(XmlWriter writer);



public void ReadXmlShema(Stream stream);

public void ReadXmlShema(string filename);

public void ReadXmlShema(TextWriter writer);

public void ReadXmlShema(XmlWriter writer);

DataTable 개체의 구조를 파일에 저장할 때는 WriteXmlSchema 메서드를 사용합니다.

dt.WriteXmlSchema(schema_fname, true);

DataTable 개체에 보관한 데이터를 저장할 때는 WriteXml 메서드를 사용합니다.

dt.WriteXml(fname, true);

DataTable 개체의 구조를 파일에서 로딩할 때는 ReadXmlSchema 메서드를 사용합니다.

dt.ReadXmlSchema(schema_fname);

파일에 있는 데이터를 DataTable 개체로 로딩할 때 ReadXml 메서드를 사용합니다.

     dt.ReadXml(fname);

다음은 설명한 메서드들을 이용하여 작성한 도서 관리 프로그램 소스 코드입니다.

using System;
using System.Data;
using System.IO;

namespace 도서_관리_프로그램
{
    class BookManager
    {
        DataTable dt = new DataTable("Books");
        readonly string schema_fname = "books.xsd";
        readonly string fname = "book.xml";
        static BookManager bm = null;

        internal static void Run()
        {
            bm = new BookManager();
            bm.Start();
            bm.Save();
        }

        private void Save()
        {
            
            dt.WriteXml(fname, true);
        }


        private void Start()
        {
            ConsoleKey key;

            while ((key = SelectMenu()) != ConsoleKey.Escape)
            {
                switch (key)
                {
                    case ConsoleKey.F1: AddBook(); break;
                    case ConsoleKey.F2: RemoveBook(); break;
                    case ConsoleKey.F3: FindBook(); break;
                    case ConsoleKey.F4: ListBook(); break;
                    default: Console.WriteLine("잘못 선택하였습니다."); break;
                }

                Console.WriteLine("아무 키나 누르세요.");
                Console.ReadKey();
            }
        }

        private void ListBook()
        {
            int row_count = dt.Rows.Count;
            Console.WriteLine("보유 도서수:{0}", row_count);
            
            foreach(DataRow dr in dt.Rows)
            {
                ViewBook(dr);
            }
        }

        private void FindBook()
        {
            string isbn = string.Empty;
            Console.WriteLine("검색할 도서의 ISBN을 입력하세요.");
            isbn = Console.ReadLine();
            DataRow dr = dt.Rows.Find(isbn);
            if (dr == null)
            {
                Console.WriteLine("존재하는 ISBN이 아닙니다.");
                return;
            }
            ViewBook(dr);
        }

        private void ViewBook(DataRow dr)
        {
            foreach (DataColumn dc in dt.Columns)
            {
                Console.WriteLine("{0}:{1}", dc.ColumnName, dr[dc]);
            }
            Console.WriteLine("-------------------------------------");
        }

        private void RemoveBook()
        {
            string isbn = string.Empty;
            Console.WriteLine("삭제할 도서의 ISBN을 입력하세요.");
            isbn = Console.ReadLine();
            DataRow dr = dt.Rows.Find(isbn);
            if (dr == null)
            {
                Console.WriteLine("존재하는 ISBN이 아닙니다.");
                return;
            }
            dt.Rows.Remove(dr);
            Console.WriteLine("삭제하였습니다.");
        }
        private void AddBook()
        {
            string isbn = string.Empty;
            string title = string.Empty;
            string author = string.Empty;
            int price = 0;

            Console.WriteLine("추가할 도서의  ISBN을 입력하세요.");
            isbn = Console.ReadLine();

            if (Exist(isbn))
            {
                Console.WriteLine("이미 존재하는 ISBN입니다.");
                return;
            }
            Console.WriteLine("도서명을 입력하세요.");
            title = Console.ReadLine();

            Console.WriteLine("저자명을 입력하세요.");
            author = Console.ReadLine();

            Console.WriteLine("가격을 입력하세요.");
            if (int.TryParse(Console.ReadLine(), out price) == false)
            {
                Console.WriteLine("잘못 입력하였습니다.");
                return;
            }

            AddBook(isbn, title, author, price); 
        }

        private void AddBook(string isbn, string title, string author, int price)
        {
            try
            {
                DataRow dr = dt.NewRow();
                dr["ISBN"] = isbn;
                dr["Title"] = title;
                dr["Author"] = author;
                dr["Price"] = price;
                dt.Rows.Add(dr);
                Console.WriteLine("{0} 추가 성공", title);
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} 추가 실패", title);
                Console.WriteLine("이유:{0}", e.Message);
            }            
        }

        private bool Exist(string isbn)
        {
            return dt.Rows.Find(isbn) != null;
        }

        private ConsoleKey SelectMenu()
        {
            Console.Clear();
            Console.WriteLine("도서 관리 프로그램 [ESC]: 종료");
            Console.WriteLine("F1:도서 추가 F2:도서 삭제 F3:도서 검색 F4:전체보기");
            return Console.ReadKey().Key;
        }

        private BookManager()
        {
            if (File.Exists(schema_fname))
            {
                dt.ReadXmlSchema(schema_fname);

                if (File.Exists(fname))
                {
                    dt.ReadXml(fname);
                }
            }
            else
            {
                TableDesign();
                dt.WriteXmlSchema(schema_fname, true);
            }
        }

        private void TableDesign()
        {
            DataColumn dc_title = new DataColumn();
            dc_title.ColumnName = "Title";
            dc_title.DataType = typeof(string);
            dc_title.AllowDBNull = false;
            dt.Columns.Add(dc_title);

            DataColumn dc_isbn = new DataColumn("ISBN", typeof(string));
            dc_isbn.Unique = true;
            dc_isbn.AllowDBNull = false;
            dt.Columns.Add(dc_isbn);
            DataColumn dc_author = new DataColumn();
            dc_author.ColumnName = "Author";
            dc_author.DataType = typeof(string);
            dc_author.AllowDBNull = false;
            dt.Columns.Add(dc_author);


            DataColumn dc_price = new DataColumn();
            dc_price.ColumnName = "Price";
            dc_price.DataType = typeof(int);
            dc_price.AllowDBNull = false;
            dt.Columns.Add(dc_price);

            DataColumn[] pkeys = new DataColumn[1];
            pkeys[0] = dc_isbn;
            dt.PrimaryKey = pkeys;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            BookManager.Run();
        }
    }
}