C++ MFC 환경

C#/Visual Studio 2019. 12. 23. 17:03
728x90

마이크로소프트 파운데이션 클래스 라이브러리(Microsoft Foundation Class Library)는 C++용 프로그램 라이브러리이다.
블로그 글을 찾아서 읽다보니
C++ 공부하는 분들 제발 MFC책부터 펼치지 말란다.
VS2008에서 사용하는 C++ 표준이라고 해봐야 옛날 고전 문법 정도가 전부다.
C++ 개발자지만, 나쁘게 이야기하면 MFC밖에 안 다뤄봤다.
C++ 개발자라 하기엔 뭔가 부족한 느낌이다.
C#으로 UI를 만들고 C++로 엔진 구현하는게 추세다.
MFC는 공식적으로 1999년에 MS가 지원을 끊었다.


C++ MFC를 사용하기 위한 기본 설치 방법이다.





MySQL 과 C++ 연동하는 걸 해보려고 검색했더니 MFC 자료가 나오길래 설치하는 방법을 적어두기는 한다.

검색결과 이건 제대로 된 방향이 아니라고 하니까 일단 C++ 문법 지식 제대로 익히는데 주력해야 하나보다.

블로그 이미지

Link2Me

,
728x90

Visual Studio 에서 C++ 포인터 주소 등 주소 할당에 대해 실행할 때 마다 메모리 주소가 다르게 변경된다.

메모리 주소를 고정시키는 방법이다.





블로그 이미지

Link2Me

,
728x90

Visual Studio 에서 자주 사용하는 단축키 정리


 라인 삭제

 CTRL + L

 라인 복사

 현재 커서가 위치한 줄에서 CTRL + C, 원하는 줄로 이동하여 CTRL + V

 코드 정렬

 CTRL + K + F

 선택 영역을 주석으로 처리

 CTRL + K, C

 선택 영역을 주석처리 제거

 CTRL + K, U

 대응하는 괄호 찾기(이동)

 CTRL + ]

 화면 글꼴 크게/작게 보기

 CTRL + 마우스 휠 누르면 화면 글꼴이 커지고 작아진다.


블로그 이미지

Link2Me

,
728x90

클래스의 멤버 변수를 private, public 으로 선언할 것인가에 따라 정보은닉, 정보공개를 고민하게 된다.

private 로 선언하면 getter 메소드, setter 메소드를 구현해야 한다.


C# 언어에서는 다양한 이유로 프로퍼티의 사용을 장려한다. 지금까지도 타입(type)에서 public 데이터 변수를 사용하거나, get/set류의 메서드를 직접 만들어서 사용하고 있다면 이제 그런 방법을 사용하지 않는 것이 좋다. 프로퍼티는 우리가 만든 타입의 값을 외부에서 접근할 수 있도록 하면서 동시에 객체지향에서 논의되는 캡슐화를 지원한다. 프로퍼티는 데이터 멤버처럼 접 근가능하면서 메서드의 형태로 구현되는 C# 언어의 요소이다.


프로퍼티(속성)를 사용하면 클래스가 구현 또는 코드를 숨기는 동시에 값을 가져오고 설정하는 방법을 공개적으로 노출할 수 있다.
- get 속성 접근자는 속성 값을 반환하고, set 접근자는 새 값을 할당하는데 사용한다.
- set 접근자의 value 키워드는 set 접근자가 할당하는 값을 정의하는데 사용한다.
- set 접근자만을 구현하면 쓰기 전용, get 접근자만을 구현하면 읽기 전용이다.
- value : set 접근자 사용 시 사용되는 암묵적 매개변수


자동구현 프로퍼티

using System;

namespace Property
{
    class Test
    {
        private int x;
        public int X   // 프로퍼티
        {
            get { return x; }
            set {
                x = value; // value : set 접근자 사용시 사용되는 암묵적 매개변수
            }
        }
    }

    class Person
    {
        public string Name { get; set; } // 자동 구현 프로퍼티
        public int Age { get; } // 읽기전용, 자동 구현 프로퍼티
        public int grade { get; } = 5; // 자동속성초기화
        public Person(string name, int age) // 생성자
        {
            this.Name = name;
            this.Age = age;
        }
        
        public override string ToString()
        {
            return $"name={Name}, age={this.Age}, grade={grade}";
        }
    }


    public class SaleItem
    {
        public string Name // 자동 구현 프로퍼티
        { get; set; }

        public decimal Price // 자동 구현 프로퍼티
        { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test t1 = new Test();
            t1.X = 5000;              // 프로퍼티 set 접근자를 통한 값 지정
            Console.WriteLine(t1.X);  // 프로퍼티 get 접근자를 통한 출력

            Person a = new Person("Tom", 14);
            Console.WriteLine(a);

            var item = new SaleItem { Name = "구두", Price = 150000 };
            Console.WriteLine($"{item.Name}의 판매 가격은 {item.Price}");
        }
    }
}


Program.cs


'C# > 문법 및 기능' 카테고리의 다른 글

C# 인터페이스  (0) 2019.08.18
C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

C# 인터페이스

- 인터페이스는 메서드, 속성(Property), 이벤트, 인덱서만을 가질 수 있으며, 이를 직접 구현하지 않는다.

- 인터페이스는 필드를 포함할 수 없다.

- 정의부분만 표현하고, 구현 부분은 상속받은 클래스에서 구현한다. (구현이라 함은 {}가 포함된 거)
- 인터페이스는 추상 멤버(abstract member)로만 구성된 추상 Base 클래스(abstract base class)와 개념적으로 유사하다.
- 클래스가 인터페이스를 가지는 경우 해당 인터페이스의 모든 멤버에 대한 구현(implementation)을 제공해야 한다.
- C# 클래스가 인터페이스를 갖는 경우 인터페이스의 모든 멤버에 대한 구현을 제공해야 한다.

- 여러개의 인터페이스를 부모로 둘 수 있다. (다중 상속 가능)
- 인터페이스로 객체를 생성할 수는 없다.

참고사항
public class Staff : IEmployee
를 보면 C#은 상속이 Class 인지, Interface 인지 구별없이 사용한다.
Java 는 Class 상속은 extends, Interface 구현은 implements 로 구별하고 있다.
그래서 C#에서는 인터페이스라는 걸 구별하기 위해 암묵적으로 대문자 I를 붙여주는 거 같다.

public class Staff : IEmployee

출처: https://link2me.tistory.com/1671 [소소한 일상 및 업무TIP 다루기]


예제 1

using System;

namespace Interface_01
{
    interface IEmployee
    {
        // 멤버 앞에 접근제한자 사용 안함
        string getName();
        void setName(string n);
        int getCounter();
    }

    public class Staff : IEmployee
    {
        // IEmployee 구현, 인터페이스라는 걸 구분하기 위해서 앞에 대문자 I를 붙인다.
        private String name;
        private int counter;
        public static int NOofEmployees;

        public string getName()
        {
            return name;
        }

        public void setName(string name)
        {
            this.name = name;
        }

        public int getCounter()
        {
            return counter;
        }

        public Staff() // 생성자
        {
            counter = ++counter + NOofEmployees;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string name;
            Console.Write("직원 수 입력: ");
            Staff.NOofEmployees = int.Parse(Console.ReadLine());

            Staff my = new Staff();
            Console.Write("신입 직원의 이름을 입력하세요: ");
            name = Console.ReadLine();
            my.setName(name);

            Console.WriteLine("▷ 직원 정보 ◁");
            Console.WriteLine("직원 번호 : {0}, 직원이름 : {1} : ", my.getCounter(),my.getName());
          
        }
    }
}


예제2 : 프로퍼티 속성을 이용한 인터페이스 구현

using System;

namespace Interface_02
{
    interface IEmployee
    {
        // 멤버 앞에 접근제한자 사용 안함
        string Name { get;set; } // 읽기, 쓰기 모두 가능한 프로퍼티
        int Counter { get; }  // 읽기 전용 프로퍼티
    }

    public class Staff : IEmployee
    {
        // IEmployee 구현, 인터페이스라는 걸 구분하기 위해서 앞에 대문자 I를 붙인다.
        private String name;
        private int counter;
        public static int NOofEmployees; // static 키워드를 사용해서 객체 생성없이 필드 사용

        public string Name  // 읽기, 쓰기 모두 가능한 프로퍼티
        {
            get { return name; }
            set { name = value; }
        }

        public int Counter  // 읽기 전용 프로퍼티
        {
            get { return counter; }
        }

        public Staff() // 생성자
        {
            counter = ++counter + NOofEmployees;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string name;
            Console.Write("직원 수 입력: ");
            Staff.NOofEmployees = int.Parse(Console.ReadLine());

            Staff my = new Staff();
            Console.Write("신입 직원의 이름을 입력하세요: ");
            name = Console.ReadLine();
            my.Name = name;

            Console.WriteLine("▷ 직원 정보 ◁");
            Console.WriteLine("직원 번호 : {0}, 직원이름 : {1} : ", my.Counter, my.Name);

        }
    }
}



Base()
this는 각각의 메모리를 구분하기위한 방법이며, 생성자를 호출하기 위한 방법으로 사용된다.
이외에 부모와 자식간의 메모리를 구분하기 위한 키워드가 바로 base키워드이다.
부모 클래스의 이름으로는 부모 클래스의 생성자를 호출할 수 없고 base 키워드를 사용해야 한다.

    public class Parent
    {
        private int i;

        public Parent(int i)
        {
            this.i = i;
        }
    }

    public class Child : Parent
    {
        private int j;

        public Child(int i, int j) : base(i)    // 부모 클래스의 생성자를 호출하려면 base 키워드를 사용해야 한다.
        {
            this.j = j;
        }
    }
 


Program.cs


'C# > 문법 및 기능' 카테고리의 다른 글

C# 프로퍼티(Property)  (0) 2019.08.19
C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

구조체는 사용자 정의 Data Type 으로 int, double 등과 같은 기본 제공 변수 유형이 아닌
새로운 유형, 여러가지 유형을 사용하기 위해 사용자가 직접 만들어 사용한다.
- 구조체를 정의하려면 struct 문을 사용한다.
- C# 구조체에 메소드, 필드, 속성등을 가질 수 있다.
- C# 구조체에 기본(Default) 생성자를 정의할 수 없다.
- C# 구조체에 소멸자를 정의할 수 없다.
- 클래스는 힙에 생성되는 참조 유형이고 구조체는 스택에 생성되는 값 유형이다.
- 구조체는 상속을 지원하지 않는다.

- 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화할 수 있다.


using System;

namespace Struct_EX
{
    class BaseClass // 부모 클래스
    {
        public int a; // 클래스의 멤버를 접근 제한자로 지정하지 않으면 멤버의 접근 수준은 무조건 private로 자동 지정됨
        int b;

        private void A() { }
        protected void B() { }

        public void C() { }

        public void ParentMethod() // 부모클래스의 ParentMethod 메소드
        {
            A();
            B();
            C();
        }
    }
    class DerivedClass : BaseClass // DerivedClass (파생) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public void ChildMethod()
        {
            //A(); // private 접근 지시어로 선언된 메소드 접근은 같은 클래스 안에서만 접근 가능
            B(); // protected 접근 지시어로 선언되었고 자식 클래스는 부모 클래스의 파생 클래스 이므로 접근 가능
            C();
        }

    }

    class Program
    {
        struct MyPoint // 클래스와 유사한 구문, 상속 불가, 인터페이스 구현 불가
        {
            public int x;
            public int y;

            public MyPoint(int x, int y) // 구조체의 생성자는 매개변수를 넣어 만들어야 한다.
            {
                this.x = x;
                this.y = y;
            }

            public override string ToString()
            {
                return string.Format("({0}, {1})", x, y);
            }
        }

        class PointC
        {
            public int x;
            public int y;
            public PointC(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            parent.a = 1; // 보호수준 때문에 접근 불가
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.ParentMethod();
            child.ChildMethod();
            child.C();

            MyPoint p; // 클래스와 달리 구조체는 new 연산자를 사용하지 않고 인스턴스화할 수 있다.
            p.x = 55;
            p.y = 77;
            Console.WriteLine("구조체 : p.x = {0}, p.y = {1}", p.x, p.y);
            Console.WriteLine(p.ToString());

            MyPoint p1 = new MyPoint(11,22); //구조체 선언
            PointC p2 = new PointC(11,22);  //클래스 선언
            MyPoint p3 = p1; // 값에 의한 복사 (구조체는 스택에 생성되는 값 타입)
            PointC p4 = p2; // 참조에 의한 복사 (클래스는 힙에 생성되는 참조 타입으로 힙의 주소를 전달)
            Console.WriteLine("구조체 : p1.x = {0}, p1.y = {1}", p1.x, p1.y);
            Console.WriteLine("클래스 : p2.x = {0}, p2.y = {1}", p2.x, p2.y);

            p3.x = 33;
            p4.x = 44;
            Console.WriteLine("구조체 : 값에 의한 복사 p1.x = {0}, p3.x = {1}", p1.x, p3.x);

            // 구조체는 스택영역에 값이 직접 들어가서 깊은 복사가 된다.

            Console.WriteLine("클래스 : 참조에 의한 복사 p2.x = {0}, p4.x = {1}", p2.x, p4.x);
            // 클래스는 참조하는 주소가 복사되면서 스택영역의 변수가 같은 힙영역을 가리킨다.
        }
    }
}



'C# > 문법 및 기능' 카테고리의 다른 글

C# 프로퍼티(Property)  (0) 2019.08.19
C# 인터페이스  (0) 2019.08.18
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
블로그 이미지

Link2Me

,
728x90

접근 제한자(Access Modifier) : 외부로부터 타입(class, struct, inteface, delegate )나 위 타입들의 멤버들(method, property, event, field)로의 접근을 제한할 때 사용한다.


클래스 멤버는 5가지의 접근 제한자를 (public, internal, private, protected, protected internal) 모두 가질 수 있지만, 구조체(struct) 멤버는 상속이 되지 않으므로 3가지의 접근 제한자만 (public, internal, private) 가질 수 있다.


접근 제한자

클래스 내부

외부 클래스

파생(자식) 클래스

프로젝트

 public





 protected


 


 

 internal



 

 private

 

 

 

 protected internal


 

 


어셈블리는 하나의 단일한 단위로 존재하는 .NET의 실행 가능한 프로그램 또는 실행 프로그램의 일부이며  실행 및 배포의 단위라고 할 수 있다. C# 응용 프로그램 작성의 결과로 생긴 .exe 파일, 클래스 라이브러리 작성의 결과인 DLL이 각각 하나의 어셈블리 이다.
하나의 단일한 어셈블리 안의 모든 코드는 하나의 단일한 단위로 빌드, 배포되며 버전 번호가 부여되는데 각 어셈블리는 다른 프로그램들이 사용 할 수 있는 pulic class, 속성, 메소드 등을 노출하고, private으로 선언된 것들은 모두 어셈블리 안에 은폐된다.


internal
동일한 어셈블리 내에 있는 다른 타입들이 접근할 수 있다.


protected
파생 클래스에서 이 클래스 멤버에 접근할 수 있다.

private
클래스 내부와 구조체 내에서만 멤버에 접근 가능하다.


using System;

namespace ClassModifier
{
    class BaseClass // 부모 클래스
    {
        int a; // 클래스의 멤버를 접근 제한자로 지정하지 않으면 멤버의 접근 수준은 무조건 private로 자동 지정됨
        int b;

        private void A() { }
        protected void B() { }

        public void C() { }

        public void ParentMethod() // 부모클래스의 ParentMethod 메소드
        {
            A();
            B();
            C();
        }
    }
    class DerivedClass : BaseClass // DerivedClass (파생) 클래스는 BaseClass(부모클래스)를 상속받는다
    {
        public void ChildMethod()
        {
            //A(); // private 접근 지시어로 선언된 메소드 접근은 같은 클래스 안에서만 접근 가능
            B(); // protected 접근 지시어로 선언되었고 자식 클래스는 부모 클래스의 파생 클래스 이므로 접근 가능
            C();
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            BaseClass parent = new BaseClass(); // Baseclass(부모) 클래스로 새 객체를 생성한다.
            parent.a = 1; // 보호수준 때문에 접근 불가
            DerivedClass child = new DerivedClass(); // DerivedClass(자식) 클래스로 새 객체를 생성한다.
            parent.ParentMethod();
            child.ChildMethod();
            child.C();
        }
    }
}



'C# > 문법 및 기능' 카테고리의 다른 글

C# 인터페이스  (0) 2019.08.18
C# 구조체(Struct)  (0) 2019.08.14
자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
블로그 이미지

Link2Me

,
728x90

C# 동영상 강좌를 듣기 위해 Visual Studio Community 2019 버전을 설치했다.

그런데 컴파일(CTRL + F5)을 해보면 "9664 프로세스가 0 코드로 인해 종료되었습니다."가 매번 나온다.


종료 상태가 0이면 프로그램이 정상 종료했다는 뜻이란다.


이 메시지를 없애는 방법을 찾아봤더니

문구를 없애는 방법으로 [도구] → [옵션] → [디버깅] → [일반] → [체크] 디버깅이 중지되면 자동으로 콘솔 닫기

를 해주면 된다고 나온다.





블로그 이미지

Link2Me

,
728x90

IP Time 공유기를 사용하여 접속하면 보통 사설 IP 주소를 사용하게 된다.

내 PC의 공인 IP주소를 알아내는 코드는 Web 파싱을 이용하면 쉽다.


public static string getMyPublicIP()
{
    WebRequest request = WebRequest.Create("http://www.findip.kr");
    WebResponse response = request.GetResponse();
    StreamReader stream = new StreamReader(response.GetResponseStream());

    // 주소에 있는 텍스트 모두를 긁어 저장
    string firstStr = stream.ReadToEnd();
    // 파싱할 부분의 시작부분 검색
    int index1 = firstStr.IndexOf("<h1> 내 아이피 주소(My IP Address) :") + 31;
    // 끝부분 검색
    int index2 = firstStr.IndexOf("</h1>");
    //다시 담기
    string str = firstStr.Substring(index1, index2 - index1);
    return str;
}



블로그 이미지

Link2Me

,
728x90

Web 로그인 화면을 띄우고 ID 와 PW를 입력하고 클릭하면 로그인된 화면이 보일 것이다.

이 기능을 C#에서 처리하는 방법이다.

아주 간단하게 기능만 테스트 해 본 거라 username 과 password 를 직접 입력하는 방식으로 구현해봤지만 자동로그인하면서 저장한 값을 불러다가 처리하는 것이 좋을 듯하다.


webBrowser1.Document.GetElementById("username").InnerText = "xxxxx";

대신에

webBrowser1.Document.GetElementById("username").SetAttribute("value", "xxxxx") ;

를 해도 결과는 동일하다.


InvokeMember("click") : 스크립트 언어로 현재 HTML 페이지에 정의된 함수를 실행한다.

WebBrowser 로딩이 끝났을 때 실행해야 한다.


webBrowser1_DocumentCompleted 메소드는 브라우져에 웹페이지가 모두 Load 되었을 때 발생하는 이벤트다.

이것과 동일하게 처리하는 것이

while (webBrowser1.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
{
    Application.DoEvents();
}


Web 화면을 읽어오고 나서 Loading 이 완전히 끝나지 않은 상태에서 값을 전달하면 null 에러가 발생한다.



private void Form1_Load(object sender, EventArgs e)
{
   // From Web
    var url = "http://aaa.com/?r=home&system=iframe.login&iframe=Y&referer=%2F%3F";
    webBrowser1.Navigate(url);
    webBrowser1.ScriptErrorsSuppressed = true;
    while (webBrowser1.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }


    HtmlDocument doc = webBrowser1.Document;

    doc.GetElementById("username").InnerText = "xxxxx";
    doc.GetElementById("password").InnerText = "yyyyy";
    // 특정 엘리먼트를 호출하여 이벤트 처리
    webBrowser1.Document.GetElementById("login_btn").InvokeMember("click");

}

private void SuppressScriptErrorsOnly(WebBrowser browser)
{
    // Ensure that ScriptErrorsSuppressed is set to false.
    browser.ScriptErrorsSuppressed = false;

    // Handle DocumentCompleted to gain access to the Document object.
    browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(
            webBrowser1_DocumentCompleted);
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    ((WebBrowser)sender).Document.Window.Error +=  new HtmlElementErrorEventHandler(Window_Error);          
}

private void Window_Error(object sender, HtmlElementErrorEventArgs e)
{
    // Ignore the error and suppress the error dialog box.
    e.Handled = true;
}


참고하면 도움될 사이트

https://stackoverflow.com/questions/32904235/c-sharp-get-element-by-name


https://stackoverflow.com/questions/16787495/click-on-html-element-by-class-using-webbrowser-c-sharp


https://ddingjo.blogspot.kr/2017/04/c-html.html

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

C# 과 Web  (0) 2018.03.10
C# Web 접속 로그인함수 만들기(HttpClient 방식)  (0) 2016.11.14
C# webFile 다운로드 함수  (0) 2016.11.12
C# GetAsyncDataFromWeb  (0) 2016.08.21
C# GetDataFromWeb 사용자 함수  (0) 2016.08.20
블로그 이미지

Link2Me

,

C# 과 Web

C#/통신 2018. 3. 10. 15:11
728x90

C# 에서 Web 페이지를 보여주는 코드다.

일부 jQuery 로 된 것을 읽어오지 못하는 것이 있기는 하지만 로그인처리라든가 이런것은 전부 잘 된다.


도구상자 => 공용콘트롤 => Webbrowser 를 선택하여 Form 에 Drop & Drop 한다.



private void Form1_Load(object sender, EventArgs e)
{

   // 폼 크기를 풀스크린으로
   FormBorderStyle = FormBorderStyle.Sizable;
   WindowState = FormWindowState.Maximized;

   // From Web
    var url = "http://aaa.com/";
    webBrowser1.Navigate(url);
    webBrowser1.ScriptErrorsSuppressed = true;
}

private void SuppressScriptErrorsOnly(WebBrowser browser)
{
    // Ensure that ScriptErrorsSuppressed is set to false.
    browser.ScriptErrorsSuppressed = false;

    // Handle DocumentCompleted to gain access to the Document object.
    browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(
            webBrowser1_DocumentCompleted);
}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    ((WebBrowser)sender).Document.Window.Error +=  new HtmlElementErrorEventHandler(Window_Error);
}

private void Window_Error(object sender, HtmlElementErrorEventArgs e)
{
    // Ignore the error and suppress the error dialog box.
    e.Handled = true;
}

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

C# Web 자동로그인 처리  (1) 2018.03.15
C# Web 접속 로그인함수 만들기(HttpClient 방식)  (0) 2016.11.14
C# webFile 다운로드 함수  (0) 2016.11.12
C# GetAsyncDataFromWeb  (0) 2016.08.21
C# GetDataFromWeb 사용자 함수  (0) 2016.08.20
블로그 이미지

Link2Me

,
728x90

Java 와 C#이 어떻게 다른지 설명이 잘된 글이 있어서 가져왔다.


출처 : http://www.elex.pe.kr/entry/Java-cf-C-Sharp

프로그램 구조

Java

package hello;


public class HelloWorld {
   public static void main(String[] args) {
      String name = "Java";

      // 매개변수를 확인
      if (args.length == 1)
         name = args[0];

      System.out.println("Hello, " + name + "!");
    }
}

C#

using System; 

namespace Hello {
   public class HelloWorld {
      public static void Main(string[] args) {
         string name = "C#";

         // 매개변수를 확인
         if (args.Length == 1)
            name = args[0];

         Console.WriteLine("Hello, " + name + "!");
      }
   }
}

Java 소스 파일의 확장자는 *.java이고, C#은 *.cs이다.

Java는 클래스마다 별도의 파일을 작성해야 하고 클래스명과 파일명이 일치해야 하지만, C#에서는 하나 이상의 최상위 클래스를 작성할 수 있고 파일명에 대한 제한도 없다.

Java

package harding.compsci.graphics;










// 단일 클래스를 임포트
import harding.compsci.graphics.Rectangle;
// 여러 클래스를 임포트
import harding.compsci.graphics.*; 

C#

namespace Harding.Compsci.Graphics {
  ...
}
또는
namespace Harding {
  namespace Compsci {
    namespace Graphics {
      ...
    }
  }
}
// 단일 클래스를 임포트
using Rectangle = Harding.CompSci.Graphics.Rectangle;
// 여러 클래스를 임포트
using Harding.Compsci.Graphics;

Java는 소스 코드의 첫 줄에 package를 선언하지만, C#에서는 namespace 키워드를 사용해서 블록으로 묶는다. C#에서는 하나의 소스 코드 파일에 여러 개의 네임스페이스를 포함시는 것도 가능하다.

Java의 import 키워드 대신, C#에서는 using 키워드를 사용한다. using 키워드를 namespace 블록 내부에 사용할 수도 있다. using 키워드를 사용해서 별칭을 지정할 수도 있다.

주석

Java

// 한 줄 주석
/* 여러 줄
    주석  */
/** 자바독 문서화 주석 */

C#

// 한 줄 주석
/* 여러 줄
    주석  */
/// 한 줄 XML 주석
/** 여러 줄 XML 주석 */

자료형

Java

원시 자료형
boolean
byte
char
short, int, long
float, double


참조 자료형
Object   (다른 모든 클래스들의 부모 클래스)
String
arrays, classes, interfaces

형 변환
// 정수를 문자열로 
int x = 123; 
String y = Integer.toString(x);  // y is "123"
// 문자열을 정수로
y = "456"; 
x = Integer.parseInt(y);   // x is 456
// 부동소수를 정수로
double z = 3.5; 
x = (int) z;   // x는 3  (소수부는 잘림)

C#

값 타입
bool
byte, sbyte
char
short, ushort, int, uint, long, ulong
float, double, decimal
structures, enumerations

참조 자료형
object    ( 다른 모든 클래스들의 부모 클래스)
string
arrays, classes, interfaces, delegates

형 변환
// 정수를 문자열로 
int x = 123; 
String y = x.ToString();  // y is "123"
// 문자열을 정수로
y = "456"; 
x = int.Parse(y);   // 또는 x = Convert.ToInt32(y);
// 부동소수를 정수로
double z = 3.5; 
x = (int) z;   // x는 3  (소수부는 잘림)

Java에서 지원되는 원시 자료형과 더불어, C#에서는 부호 없는(unsigned) 자료형과 128비트 부동 소수 형식(decimal)을 추가로 지원한다.

Java에서는 원시 자료형이 존재하고 각각의 래퍼 클래스가 존재하지만, C#에서 모든 원시 자료형은 System 네임스페이스의 객체이며 각각 별칭이 존재한다.

Java의 boolean은 C#에서 bool이다.

상수

Java

// 생성자에서 초기화 될 수 있음
final double PI = 3.14;

C#

const double PI = 3.14;

// const 또는 변수에 지정할 수 있음. 생성자에서 초기화 될 수 있음.
readonly int MAX_HEIGHT = 9;

Java에서는 final 키워드를, C#에서는 const와 readonly 키워드를 사용한다.

const 키워드를 사용하면 런타임시에 값을 변경할 수 없지만, readonly 키워드를 지정하면 런타임시에 단 한번 값을 지정할 수 있다.

열거형

Java

enum Action {Start, Stop, Rewind, Forward};
// 특수한 형태의 클래스이다. 
enum Status {
  Flunk(50), Pass(70), Excel(90);
  private final int value;
  Status(int value) { this.value = value; }
  public int value() { return value; } 
};
Action a = Action.Stop;
if (a != Action.Start)
  System.out.println(a);      // Prints "Stop"
Status s = Status.Pass;
System.out.println(s.value());      // Prints "70"

C#

enum Action {Start, Stop, Rewind, Forward};
enum Status {Flunk = 50, Pass = 70, Excel = 90};






Action a = Action.Stop;
if (a != Action.Start)
  Console.WriteLine(a);             // Prints "Stop"
Status s = Status.Pass;
Console.WriteLine((int) s);       // Prints "70"

Java 1.5 이상에서 enum을 지원한다.

C# 3.0 이상에서는 확장메서드를 통해서 enum 타입에 메서드를 정의할 수 있다.

연산자

Java

비교
==  <  >  <=  >=  !=

산술
+  -  *  /
%  (mod)
/   (integer division if both operands are ints)
Math.Pow(x, y)

할당
=  +=  -=  *=  /=   %=   &=  |=  ^=  <<=  >>=  
>>>= ++ -- 비트 & | ^ ~ << >> >>> 논리 && || & | ^ ! 문자열 결합 +

C#

비교
==  <  >  <=  >=  !=

산술
+  -  *  /
%  (mod)
/   (integer division if both operands are ints)
Math.Pow(x, y)

할당
=  +=  -=  *=  /=   %=  &=  |=  ^=  <<=  >>=  ++  --


비트
&  |  ^   ~  <<  >>

논리
&&  ||  &  |   ^   !

문자열 결합
+

연산자 오버로딩
public static ComplexNumber operator+(ComplexNumber a, ComplexNumber b) { ...

Java의 >>> 연산자는 C#에서 사용할 수 없다. 이는 부호없는 자료형이 지원되기 때문이다.

C#의 checked, unchecked 키워드를 사용해서 오버플로우를 검사할 수 있다.

C#에서는 연산자 오버로딩을 위해 operator 키워드를 지원한다.

연산자 오버로딩은 static 메서드로 선언하고 메서드 이름 대신에 operator 키워드와 연산자 심볼을 붙인다.

조건문

Java

greeting = age < 20 ? "What's up?" : "Hello";

if (x < y) 
  System.out.println("greater");

if (x != 100) {    
  x *= 5; 
  y *= 2; 
} 
else 
  z *= 6;

int selection = 2;
switch (selection) { // byte, short, int, char, enum
  case 1: x++;   // break가 없으면 다음으로 넘어간다
  case 2: y++;   break; 
  case 3: z++;   break; 
  default: other++;
}

C#

greeting = age < 20 ? "What's up?" : "Hello";

if (x < y)  
  Console.WriteLine("greater");

if (x != 100) {    
  x *= 5; 
  y *= 2; 
} 
else 
  z *= 6;

string color = "red";
switch (color) {    //자료형 제한이 없다.
  case "red":    r++;    break;  // break 꼭 필요
  case "blue":   b++;   break; 
  case "green": g++;   break; 
  default: other++;     break; 
}

Java 7이후부터 switch문에 문자열을 사용할 수 있다.

Java와 달리 C#에서는 case문 다음에 반드시 break문이 존재해야 한다.

반복문

Java

while (i < 10) 
  i++;

for (i = 2; i <= 10; i += 2) 
  System.out.println(i);

do 
  i++; 
while (i < 10);

for (int i : numArray)  // foreach construct  
  sum += i;

import java.util.ArrayList;
ArrayList<Object> list = new ArrayList<Object>();
list.add(10); 
list.add("Bisons");
list.add(2.3);    
for (Object o : list)
  System.out.println(o);

C#

while (i < 10) 
  i++;

for (i = 2; i <= 10; i += 2) 
  Console.WriteLine(i);

do 
  i++; 
while (i < 10);

foreach (int i in numArray)  
  sum += i;
 
using System.Collections;
ArrayList list = new ArrayList();
list.Add(10);
list.Add("Bisons");
list.Add(2.3);
foreach (Object o in list)
  Console.WriteLine(o);

배열

Java

int nums[] = {1, 2, 3};   
     또는   int[] nums = {1, 2, 3};

for (int i = 0; i < nums.length; i++)
  System.out.println(nums[i]);

String names[] = new String[5];
names[0] = "David";

float twoD[][] = new float[rows][cols];
twoD[2][0] = 4.5;

int[][] jagged = new int[5][]; 
jagged[0] = new int[5]; 
jagged[1] = new int[2]; 
jagged[2] = new int[3]; 
jagged[0][4] = 5;

C#

int[] nums = {1, 2, 3};


for (int i = 0; i < nums.Length; i++)
  Console.WriteLine(nums[i]);

string[] names = new string[5];
names[0] = "David";

float[,] twoD = new float[rows, cols];
twoD[2,0] = 4.5f;

int[][] jagged = new int[3][] {
    new int[5], new int[2], new int[3] }; 
jagged[0][4] = 5;

Java와 달리 C#에서는 배열을 나타내는 대괄호 []는 반드시 자료형 다음에 와야 한다.

배열의 초기화 시에도, Java와 달리 C#에서는 배열의 크기와 초기값의 수가 일치해야 한다.

C#에서는 Jagged 배열 외에 다차원 배열을 추가로 지원한다.

메서드

Java

// 값을 반환
int Add(int x, int y) { 
   return x + y; 
}

int sum = Add(2, 3);
// 결과값을 반환하지 않음
void PrintSum(int x, int y) { 
   System.out.println(x + y); 
}
PrintSum(2, 3); 

// 값에 의한 전달
void TestFunc(int x, Point p) {
   x++; 
   p.x++;       // 객체 값 변경
   p = null;    // 객체 참조를 제거 
}
class Point { 
   public int x, y; 
}
Point p = new Point(); 
p.x = 2; 
int a = 1; 
TestFunc(a, p);
System.out.println(a + " " + p.x + " " + (p == null) );  
// 1 3 false // 임의의 갯수의 매개변수 int Sum(int ... nums) { int sum = 0; for (int i : nums) sum += i; return sum; } int total = Sum(4, 3, 2, 1); // returns 10

C#

// 값을 반환
int Add(int x, int y) { 
   return x + y; 
}

int sum = Add(2, 3);
// 결과값을 반환하지 않음
void PrintSum(int x, int y) { 
   Console.WriteLine(x + y); 
}
PrintSum(2, 3); 

// 값에 의한 전달, ref, out
void TestFunc(int x, ref int y, out int z, Point p1, ref Point p2) { 
   x++;  y++;  z = 5; 
   p1.x++;       // 객체 값 변경     
   p1 = null;    // 객체 참조를 제거 
   p2 = null;   // 객체 참조를 제거 
}
class Point { 
   public int x, y; 
}
Point p1 = new Point(); 
Point p2 = new Point(); 
p1.x = 2; 
int a = 1, b = 1, c;   // out은 초기화 필요 없음
TestFunc(a, ref b, out c, p1, ref p2); 
Console.WriteLine("{0} {1} {2} {3} {4}", 
   a, b, c, p1.x, p2 == null);   // 1 2 5 3 True

// 임의의 갯수의 매개변수
int Sum(params int[] nums) {
  int sum = 0;
  foreach (int i in nums)
    sum += i;
  return sum;
}
int total = Sum(4, 3, 2, 1);   // returns 10

C#에서는 값 형식의 데이터를 참조 형식으로 매개변수를 전달하기 위해서 ref, out 키워드를 지원한다.

ref의 경우 사용하기 전에 반드시 초기화 되어 있어야 하고, out의 경우 메서드 내에서 사용하기 전에 값을 할당해야 한다.

임의의 갯수의 매개변수를 전달 받으려는 경우, Java는 ...을, C#은 params 키워드를 사용한다.

문자열

Java

// 결합
String school = "Harding "; 
school = school + "University";   // school is "Harding University"

// 비교
String mascot = "Bisons"; 
if (mascot == "Bisons")    // 틀려!
if (mascot.equals("Bisons"))   // true
if (mascot.equalsIgnoreCase("BISONS"))   // true
if (mascot.compareTo("Bisons") == 0)   // true
System.out.println(mascot.substring(2, 5));   // Prints "son"

// 날짜
java.util.Calendar c 
  = new java.util.GregorianCalendar(1973, 10, 12);
String s 
  = String.format("My birthday: %1$tb %1$te, %1$tY", c);

// 조작가능한 문자열 
StringBuffer buffer = new StringBuffer("two "); 
buffer.append("three "); 
buffer.insert(0, "one "); 
buffer.replace(4, 7, "TWO"); 
System.out.println(buffer);     // Prints "one TWO three"

String path = "\\\\FileShare\\Directory\\file.txt";

C#

// 결합
string school = "Harding "; 
school = school + "University";   // school is "Harding University"

// 비교
string mascot = "Bisons"; 
if (mascot == "Bisons")    // true
if (mascot.Equals("Bisons"))   // true
if (mascot.ToUpper().Equals("BISONS"))   // true
if (mascot.CompareTo("Bisons") == 0)    // true
Console.WriteLine(mascot.Substring(2, 3));    // Prints "son"

// 날짜
DateTime dt 
  = new DateTime(1973, 10, 12);
string s 
  = "My birthday: " + dt.ToString("MMM dd, yyyy");

// 조작가능한 문자열 
System.Text.StringBuilder buffer = 
new System.Text.StringBuilder("two "); buffer.Append("three "); buffer.Insert(0, "one "); buffer.Replace("two", "TWO"); Console.WriteLine(buffer); // Prints "one TWO three" string path = @"\\FileShare\Directory\file.txt";

문자열 비교시에, Java는 equals() 메서드를 사용하지만, C#에서는 == 또는 != 연산자를 사용할 수 있다.

C#에서는 변수에 할당되는 문자열 앞에 @을 붙여서 이스케잎 문자를 효율적으로 처리할 수 있다.

예외처리

Java

// 메서드에서 예외를 던질 수 있도록 선언되어야 함
Exception ex 
  = new Exception("Something is really wrong."); 
throw ex;  

try {
  y = 0; 
  x = 10 / y;
} catch (Exception ex) {
  System.out.println(ex.getMessage()); 
} finally {
  // Code that always gets executed
}

C#

Exception up 
  = new Exception("Something is really wrong."); 
throw up;  // ha ha

try {
  y = 0; 
  x = 10 / y;
} catch (Exception ex) { // 매개변수가 없어도 됨
  Console.WriteLine(ex.Message); 
} finally {
  // Code that always gets executed
}

C#의 catch 블록에서 매개변수를 생략할 수도 있다.

C#에서는 throws 키워드가 없다.

클래스 / 인터페이스

Java

접근 키워드
public
private
protected
static



// 상속
class FootballGame extends Competition {
  ...
}

// 인터페이스
interface IAlarmClock {
  ...
}

// 인터페이스의 상속
interface IAlarmClock extends IClock {
  ...
}

// 인터페이스 구현
class WristWatch implements IAlarmClock, ITimer {
   ...
}

C#

접근 키워드
public
private
internal
protected
protected internal
static

// 상속
class FootballGame : Competition {
  ...
}

// 인터페이스
interface IAlarmClock {
  ...
}

// 인터페이스의 상속
interface IAlarmClock : IClock {
  ...
}

// 인터페이스 구현
class WristWatch : IAlarmClock, ITimer {
   ...
}

Java의 기본 접근 제한자는 동일 패키지 내에서 접근 가능인 반면, C#에서는 private이다.

C#의 internal 키워드는 현재 어셈블리 내에서만 접근 가능하도록 지정하는 것이며, 어셈블리는 Java의 Jar파일과 유사한 개념이다.

Java에서 클래스가 더이상 상속 될 수 없도록 지정하는 final 키워드 대신, C#에서는 sealed 키워드를 사용한다.

Java에서 상속과 구현을 나타내는 키워드인 extends와 implements 대신, C#에서는 :을 사용한다.

Java의 super 키워드 대신, C#에서는 base 키워드를 사용한다.

Java와 달리, C#에서는 오버라이드 될 메서드에는 virtual 키워드를 오버라이드 하는 메서드에는 override 키워드를 사용한다.

C#에서는 인덱서를 지원하므로 이를 이용하면 클래스나 구조체를 배열처럼 다룰 수 있다.

객체

Java

SuperHero hero = new SuperHero();
hero.setName("SpamMan"); 
hero.setPowerLevel(3); 

hero.Defend("Laura Jones");
SuperHero.Rest();  // 정적 메서드 호출
SuperHero hero2 = hero;   // 동일한 객체를 참조

hero2.setName("WormWoman"); 
System.out.println(hero.getName()); 

hero = null;   // Free the object
if (hero == null)
  hero = new SuperHero();
Object obj = new SuperHero(); 
System.out.println("object's type: " + obj.getClass().toString()); 
if (obj instanceof SuperHero) 
  System.out.println("Is a SuperHero object.");

C#

SuperHero hero = new SuperHero(); 
hero.Name = "SpamMan"; 
hero.PowerLevel = 3;

hero.Defend("Laura Jones");
SuperHero.Rest();   // 정적 메서드 호출
SuperHero hero2 = hero;   // 동일한 객체를 참조
 
hero2.Name = "WormWoman"; 
Console.WriteLine(hero.Name);  

hero = null ;   // Free the object
if (hero == null)
  hero = new SuperHero();
Object obj = new SuperHero(); 
Console.WriteLine("object's type: " + obj.GetType().ToString()); 
if (obj is SuperHero) 
  Console.WriteLine("Is a SuperHero object.");

생성자 / 파괴자

Java

class SuperHero {
  private int mPowerLevel;

  public SuperHero() {
    mPowerLevel = 0;
  }

  public SuperHero(int powerLevel) {
    this.mPowerLevel= powerLevel;
  }

  // 파괴자는 없음
  protected void finalize() throws Throwable { 
    super.finalize();   // 항상 부모 요소를 호출
  }
}

C#

class SuperHero {
  private int mPowerLevel;

  public SuperHero() {
     mPowerLevel = 0;
  }

  public SuperHero(int powerLevel) {
    this.mPowerLevel= powerLevel; 
  }

  ~SuperHero() {
    // Destructor code to free unmanaged resources.
    // Implicitly creates a Finalize method.
  }
}

Java에서는 finalize() 메서드를 사용해서 가비지 컬렉터에 의해 인스턴스가 정리되기 직전에 실행될 메서드를 지정하는 반면, C#에서는 매개변수 없는 생성자와 유사한 형식으로 지정하며 이름 앞에 물결 표시(~)를 붙인다.

속성

Java

private int mSize;

public int getSize() { return mSize; } 
public void setSize(int value) {
  if (value < 0) 
    mSize = 0; 
  else 
    mSize = value; 
}


int s = shoe.getSize();
shoe.setSize(s+1);

C#

private int mSize;

public int Size { 
  get { return mSize; } 
  set { 
    if (value < 0) 
      mSize = 0; 
    else 
      mSize = value; 
  } 
}

shoe.Size++;

C#에서는 private 멤버 변수의 getter와 setter 메서드를 처리하는 get, set 키워드를 지원한다.

구조체

Java

x

C#

x

x

프로그램 구조

Java

 

C#

struct StudentRecord {
  public string name;
  public float gpa;

  public StudentRecord(string name, float gpa) {
    this.name = name;
    this.gpa = gpa;
  }
}

StudentRecord stu = new StudentRecord("Bob", 3.5f);
StudentRecord stu2 = stu;  

stu2.name = "Sue";
Console.WriteLine(stu.name);    // Prints "Bob"
Console.WriteLine(stu2.name);   // Prints "Sue"

C#에서는 클래스와 유사한 구조체라는 자료형을 지원한다. 단, 구조체는 상속이 불가능하고, 참조형 데이터가 아니다.

이벤트

Java

 

C#

window.ClickedEvent += MyEventHandler;

Java의 경우 이벤트를 수신할 클래스에서 Listener를 구현한 후 이벤트를 발생시키는 객체에 등록(register)하지만, C#에서 이벤트는 이벤트를 발생시키는 객체의 멤버이므로 이벤트 핸들러 메서드를 추가하기만 하면 된다.

C#에서는 이벤트 핸들러 메서드를 위해 delegate 키워드를 제공한다. 딜리게이트는 함수 포인터와 유사한 개념이다.

콘솔 입출력

Java

java.io.DataInput in 
= new java.io.DataInputStream(System.in);
System.out.print("What is your name? ");
String name = in.readLine();

System.out.print("How old are you? ");
int age = Integer.parseInt(in.readLine());
System.out.println(name + " is " + age + " years old.");
int c = System.in.read();   // Read single char
System.out.println(c);      // Prints 65 if user enters "A"

// The studio costs $499.00 for 3 months.
System.out.printf("The %s costs $%.2f for %d months.%n", "studio", 499.0, 3);

// Today is 06/25/04
System.out.printf("Today is %tD\n", new java.util.Date());

C#

Console.Write("What's your name? ");
string name = Console.ReadLine();



Console.Write("How old are you? ");
int age = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("{0} is {1} years old.", name, age);
// 또는
Console.WriteLine(name + " is " + age + " years old.");
int c = Console.Read(); // Read single char Console.WriteLine(c); // Prints 65 if user enters "A" // The studio costs $499.00 for 3 months. Console.WriteLine("The {0} costs {1:C} for {2} months.\n",
"studio", 499.0, 3); // Today is 06/25/2004 Console.WriteLine("Today is " + DateTime.Now.ToShortDateString());

파일 입출력

Java

import java.io.*;

// Character stream writing
FileWriter writer 
  = new FileWriter("c:\\myfile.txt");
writer.write("Out to file.\n");
writer.close();

// Character stream reading
FileReader reader 
  = new FileReader("c:\\myfile.txt");
BufferedReader br = new BufferedReader(reader);
String line = br.readLine(); 
while (line != null) {
  System.out.println(line); 
  line = br.readLine(); 
} 
reader.close();

// Binary stream writing
FileOutputStream out 
  = new FileOutputStream("c:\\myfile.dat");
out.write("Text data".getBytes());
out.write(123);
out.close();

// Binary stream reading
FileInputStream in 
  = new FileInputStream("c:\\myfile.dat");
byte buff[] = new byte[9];
in.read(buff, 0, 9);   // Read first 9 bytes into buff
String s = new String(buff);
int num = in.read();   // Next is 123
in.close();

C#

using System.IO;

// Character stream writing
StreamWriter writer 
  = File.CreateText("c:\\myfile.txt"); 
writer.WriteLine("Out to file."); 
writer.Close();

// Character stream reading
StreamReader reader 
  = File.OpenText("c:\\myfile.txt"); 
string line = reader.ReadLine(); 
while (line != null) {
  Console.WriteLine(line); 
  line = reader.ReadLine(); 
} 
reader.Close();



// Binary stream writing
BinaryWriter out 
  = new BinaryWriter(File.OpenWrite("c:\\myfile.dat")); 
out.Write("Text data"); 
out.Write(123); 
out.Close();

// Binary stream reading
BinaryReader in 
  = new BinaryReader(File.OpenRead("c:\\myfile.dat")); 
string s = in.ReadString(); 
int num = in.ReadInt32(); 
in.Close();

C#에는 이 외에 인덱서, unsafe, fixed 등이 더 있음.

참고 자료:

http://www.harding.edu/fmccown/java_csharp_comparison.html

http://msdn.microsoft.com/en-us/library/ms228602(v=vs.90)

 


'C# > 문법 및 기능' 카테고리의 다른 글

C# 구조체(Struct)  (0) 2019.08.14
C# 접근 제한자(Access Modifier)  (0) 2019.08.13
C# NameValueCollection  (0) 2016.03.20
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
블로그 이미지

Link2Me

,
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

C# 에서 Web 접속방식으로 로그인 처리를 위한 방법을 소개한다.


http://link2me.tistory.com/970 에 기본적인 사항을 적어두었다.


HttpClient 방식으로 로그인하는 방법을 알아두면 여러모로 유용하다.

로그인 뿐만 아니라 Web 접속방식으로 데이터를 주고 받을 때 많이 활용된다.

json 형태로 데이터를 주고 받기 위한 함수만 추가로 만들어서 사용하면 된다.


string json 부분을 보면 PHP 로그인 함수 결과값을 받는다.

PHP 에서 도대체 어떤 걸 받는거지? 라고 하는 의문이 들 것이다.

PHP 결과를 받는 것은 echo 문의 결과값이다.

이 결과값이 배열일 수도 있고 단순한 텍스트일 수도 있다.

echo 문으로 출력되는 결과를 어떻게 만들 것인가 하는 것은 PHP 에서 고민하면 된다.

가령 성공하면 1, 실패하면 0, DB접속 실패하면 -1 이런식으로 PHP 로그인 함수를 만들어도 된다.

개발자의 취향에 따라 개발해서 연동하면 된다.


=== LoginForm.cs ====

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Http;
using System.Web.Script.Serialization;
using System.IO;
using System.Configuration;

namespace Dennis_Sentence
{
    public partial class frmLogin : Form
    {
        Boolean CK = false;
        private string strID;

        public frmLogin()
        {
            InitializeComponent();
        }

        public string getstrID   // ID를 알려주는 속성 설정
        {
            get { return strID; }
        }

        private void frmLogin_Load(object sender, EventArgs e)
        {
            txtID.Text = Properties.Settings.Default.LoginIDSave;
            txtPwd.Text = Properties.Settings.Default.SitePasswd;
            if (Properties.Settings.Default.LoginIDSave.Length > 0 && Properties.Settings.Default.SitePasswd.Length > 0)
            {
                IDSave.Visible = false;
                IDdelete.Visible = true;
            }
            else
            {
                IDSave.Visible = true;
                IDdelete.Visible = false;
            }
        }

        /// <summary>
        /// SQL 인젝션 필터 - Select 에서 조건절 필터링
        /// </summary>
        private static string Filtering(string inputSQL)
        {
            return inputSQL.Replace(":", "").Replace("+", "").Replace(";", "").Replace("--", "").Replace("\"", "");
        }

        private void frmLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!CK)
            {
                Application.Exit();
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {

            if (this.txtID.Text == "")
            {
                MessageBox.Show("로그인 아이디를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.txtID.Focus();
            }
            else if (this.txtPwd.Text == "")
            {
                MessageBox.Show("로그인 비밀번호를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.txtPwd.Focus();
            }
            else
            {
                if (IDSave.Checked)
                {
                    Properties.Settings.Default.LoginIDSave = txtID.Text;
                    Properties.Settings.Default.SitePasswd = txtPwd.Text;
                    Properties.Settings.Default.Save();
                }

                if (IDdelete.Checked)
                {
                    Properties.Settings.Default.LoginIDSave = string.Empty;
                    Properties.Settings.Default.SitePasswd = string.Empty;
                    Properties.Settings.Default.Save();
                }

                mySqlLogin();
            }

        }

        private void mySqlLogin()
        {
            try
            {
                var client = new HttpClient();
                var postData = new List<KeyValuePair<string, string>>();
                string URL = "http://IP주소/Login.php";
                postData.Add(new KeyValuePair<string, string>("loginID", Filtering(txtID.Text.Trim())));
                postData.Add(new KeyValuePair<string, string>("loginPW", Filtering(txtPwd.Text.Trim())));
                var formContent = new FormUrlEncodedContent(postData);
                var result = client.PostAsync(URL, formContent).Result;
                string json = result.Content.ReadAsStringAsync().Result;
                //MessageBox.Show(json);
                if (json == "1") // PHP 로그인 함수에서 로그인 성공시의 echo 결과값
                {
                    CK = true;
                    strID = txtID.Text;
                    this.Close();  // 현재 폼 닫기
                }
                else
                {
                    MessageBox.Show("로그인 실패", "Login Fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    CK = false;
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("Error :" + ex.Message);
            }
        }       

        private void btnCancel_Click(object sender, EventArgs e)
        {
            //CK = false;
            Application.Exit();  // 취소버튼을 누르면 프로그램 완전 종료 처리
        }

        private void txtPwd_KeyDown(object sender, KeyEventArgs e)  // 엔터키를 눌렀다면...
        {
            if (e.KeyCode == Keys.Enter)
            {
                btnOK_Click(sender, e);
            }
        }

        private void IDSave_CheckedChanged(object sender, EventArgs e)
        {
            if (IDdelete.Checked == true)
            {
                IDdelete.Checked = false;
            }
        }

        private void IDdelete_CheckedChanged(object sender, EventArgs e)
        {
            if (IDSave.Checked == true)
            {
                IDSave.Checked = false;
            }
        }
    }
       
}


=== Login.php ===

<?php
session_start();
@extract($_POST);
if(isset($loginID) && !empty($loginID) && isset($loginPW) && !empty($loginPW)) {

    require_once 'phpclass/dbinfo.php';
    require_once 'phpclass/dbClass.php';
    $conn=new MySQLDbClass(); // DB 함수 객체 생성
    $DB_CONNECT = $conn->isConnectDb($DB); // 안드로이드폰에서는 반드시 객체로 생성해야 정상접속
    require_once 'phpclass/loginClass.php';
    $c=new LoginClass(); // 로그인 객체 생성

    $row = $c->WebUserAuthCheck($loginID,$loginPW);  // 로그인 체크 함수
    if(is_array($row)) {
        if(!empty($row['id'])) {
            $_SESSION['userID'] = $row['id'];
            echo 1; // 로그인 성공
        } else {
            echo 0; // 로그인 실패
        }
    } else if($row == '0'){
        echo 0; // 로그인 실패
    } else {
        echo 0; // 로그인 실패
    }

}
?>


도움이 되셨다면 00 00 해 주세요. 좋은 글 작성에 큰 도움이 됩니다.

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

C# Web 자동로그인 처리  (1) 2018.03.15
C# 과 Web  (0) 2018.03.10
C# webFile 다운로드 함수  (0) 2016.11.12
C# GetAsyncDataFromWeb  (0) 2016.08.21
C# GetDataFromWeb 사용자 함수  (0) 2016.08.20
블로그 이미지

Link2Me

,
728x90

C# Web 파일을 PC에 다운로드하기 위해 만든 함수다.

사용법은 Web 파일 다운로드 게시글을 참조하면 된다.


코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace NameSpace
{
    class Folder
    {
        public static void MyFolderCreate(string myfolder)
        {
            string MyPath = MyFolder(myfolder);
            if (!Directory.Exists(MyPath))
            {
                Directory.CreateDirectory(MyPath);
            }
        }

        public static string MyFolder(string myfolder)
        {
            string UserPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // User Documents 폴더
            return UserPath + "\\" + myfolder;
        }

        public static string MyfilePath(string myfolder, string appName)
        {
            return Folder.MyFolder(myfolder) + "\\" + appName;
        }

        public static void MyFolderDelete(string path)
        {
            DeleteDirectory(path, false);
        }

        public static void DeleteDirectory(string path, bool recursive)
        {
            if (recursive)
            {
                var subfolders = Directory.GetDirectories(path);
                foreach (var subfolder in subfolders)
                {
                    DeleteDirectory(subfolder, recursive);
                }
            }

            // Get all files of the folder
            var files = Directory.GetFiles(path);
            foreach (var file in files)
            {
                var attribute = File.GetAttributes(file);
                if ((attribute & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    File.SetAttributes(file, attribute ^ FileAttributes.ReadOnly);
                }
                File.Delete(file);
            }
            Directory.Delete(path);
        }

        public static string SSplit(string _body, string _parseString, int index)
        {
            // 엑셀 VBA 에서 사용하는 Split 함수처럼 만든 사용자 함수
            string varTemp = _body.Split(new string[] { _parseString }, StringSplitOptions.None)[index];
            return varTemp;
        }
    }
}


블로그 이미지

Link2Me

,
728x90

C#에서 Web 방식으로 파일을 다운로드하는 코드이다.

오래되어 기억은 가물가물하지만 구글링도하고 블로그 검색으로 찾은 걸 약간 수정한거 같기는 하다.

최근에 SSD 이상증상으로 데이터를 살리지 못한 경험도 있고 해서 블로그에 기록해둔다.


사용법 예시

사용법 예시는 전체적으로 동작되는 걸 보여주는게 아니라 이런식으로 활용할 수 있다는 것만 간략하게 기록


private void webFileDown(string mp3sub, string mp3file)
{
    // 파일 다운로드
    string webfilePath = string.Format("http://ipaddress/{0}/{1}", mp3folder, mp3file);
    string localfilePath = Folder.MyfilePath("abcdef", mp3file);
    if (webFile.WebExists(webfilePath))
    {
        int write = webFile.DownloadFile(webfilePath, localfilePath);  // 파일 사이즈를 반환
    }
    else
    {
        MessageBox.Show("다운받을 파일이 존재하지 않습니다");
        return;
    }
}             



코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;

namespace NameSpace  // 수정해서 사용 필요
{
    class webFile
    {
        /// <summary>
        /// 웹파일 다운로드
        /// </summary>
        /// <param name="remoteFilename">웹 서버 파일</param>
        /// <param name="localFilename">PC 저장 파일</param>
        /// <returns>파일 크기를 반환</returns>
        public static int DownloadFile(String remoteFilename, String localFilename)
        {
            // Function will return the number of bytes processed to the caller. Initialize to 0 here.
            int bytesProcessed = 0;

            // Assign values to these objects here so that they can be referenced in the finally block
            Stream remoteStream = null;
            Stream localStream = null;
            WebResponse response = null;

            // Use a try/catch/finally block as both the WebRequest and Stream classes throw exceptions upon error
            try
            {
                WebRequest request = WebRequest.Create(remoteFilename); // 원격 파일 다운을 위한 객체 생성
                if (request != null)
                {
                    response = request.GetResponse(); // 서버로부터 WebResponse 오브젝트 받아옴
                    if (response != null)
                    {
                        // Once the WebResponse object has been retrieved, get the stream object associated with the response's data
                        remoteStream = response.GetResponseStream();
                        //localStream = File.Create(localFilename);  // local File 생성
                        localStream = new FileStream(localFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite);

                        byte[] buffer = new byte[1024];  // 1k 버퍼 할당
                        int bytesRead;

                        // Simple do/while loop to read from stream until no bytes are returned
                        do
                        {
                            bytesRead = remoteStream.Read(buffer, 0, buffer.Length); // 1K 바이트씩 데이터 읽기
                            localStream.Write(buffer, 0, bytesRead); // PC에 데이터 저장
                            bytesProcessed += bytesRead;  // 전체 바이트 수 체크를 위해 누적
                        } while (bytesRead > 0);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                if (response != null) response.Close(); //WebResponse객체 Close
                if (remoteStream != null) remoteStream.Close();
                if (localStream != null) localStream.Close();
            }

            return bytesProcessed;  // 수신한 전체 바이트수를 리턴(파일의 크기)
        }

        /// <summary>
        /// 웹에 파일이 존재하는지 검사하여 있으면 true 반환
        /// </summary>
        /// <param name="url">Web 파일 경로</param>
        /// <returns></returns>
        public static bool WebExists(string url)
        {
            bool ret = true;
            if (url == null)
                return false;
            HttpWebResponse response = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "HEAD";
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException)
            {
                ret = false;
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
            return ret;
        }


    }
}


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

C# 과 Web  (0) 2018.03.10
C# Web 접속 로그인함수 만들기(HttpClient 방식)  (0) 2016.11.14
C# GetAsyncDataFromWeb  (0) 2016.08.21
C# GetDataFromWeb 사용자 함수  (0) 2016.08.20
C# comboBox 에 Text, Value 추가 및 POST, JSON  (0) 2016.08.19
블로그 이미지

Link2Me

,
728x90

NAudion DLL을 이용하여 만든 MP3 Player 허접한 버전이다.


작년에 기본적인 것만 만들어보다가 회사 일이 바빠서 손도 못대다가 최근에 C# 폴더 찾아보다가 발견하여 적어두고 소스코드를 포함해서 올린다.


자동 반복재생 처리하는 것까지 만들지를 못했다.

SQLite 를 이용하면 될 거 같은데 아직 이 기능을 제대로 익히지 못했다.

그냥 인터넷에 있는 아주 허접한 것보다는 약간 더 나은 수준정도인데 이것저것 참조해서 테스트해보면서 만들다가 만 거다.


LinkPlayer.zip






블로그 이미지

Link2Me

,
728x90

집에서 23인치 모니터를 2개 사용하는 환경에서 접속할 때에는 문제점을 모르고 있었는데 노트북과 모니터를 연결하는 환경에서 접속하니까 화면이 원하는 형태로 나오지 않았다.


int screenWidth = System.Windows.Forms.SystemInformation.VirtualScreen.Width;
int screenHeight = System.Windows.Forms.SystemInformation.VirtualScreen.Height;


이렇게 변경하니까 큰 화면과 작은 화면을 모두 제대로 인식하고 정상동작한다.


if (screenWidth <= 1680)
{
    dataGridView1.Columns["sub1"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
    dataGridView1.Columns["sub2"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
    dataGridView1.Columns["sub3"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
}
else
{
    dataGridView1.Columns["sub1"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    dataGridView1.Columns["sub2"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    dataGridView1.Columns["sub3"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}





블로그 이미지

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

,