블로그 이미지
따시쿵

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2015. 6. 16. 10:49 C# with LINQ to SQL

LINQ 는 Language INtegrated Query위 약어로, 컬렉션을 편리하게 다루기 위한 목적으로 만들어진 질의 언어입니다. C# 3.0 버전에서부터 탑재한 LINQ 덕분에 프로그래머들은 데이타를 찾고 병합하고 정렬하는 코드를 작성하는 짐을 상당 부분 내려 놓을 수 있게 되었습니다.

 

기본 문법

 

  • From : 어떤 데이타 집합에서 찾을 것인가?
  • Where : 어떤 값의 데이타를 찾을 것인가? (필터 역할)
  • Orderby : 어떤 데이타 순서대로 나열할 것인가?(순서 정하기)
  • Select : 어떤 항목을 추출할 것인가?

 

예제 1 - LINQ 문을 사용하지 않고 프로그램 작성

 

키가 175 미만인 데이타만을 골라서 새 컬렉션으로 추출하는 프로그램

    class Profile
    {
        public string Name { get; set; }
        public int Height { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Profile[] arrProfile = {
                                       new Profile{Name = "이순신", Height=210},
                                       new Profile{Name = "강감찬", Height=169},
                                       new Profile{Name = "을지문덕", Height=175},
                                       new Profile{Name = "세종대왕", Height=183},
                                       new Profile{Name = "안창호", Height=159},
                                       new Profile{Name = "연개소문", Height=172}
                                   };

            // 1단계 - 키가 175 미만인 데이타를 추출함
            List<profile> profiles = new List<Profile>();
            foreach(Profile profile in arrProfile)
            {
                if (profile.Height < 175)
                    profiles.Add(profile);
            }

            // 2단계 - 키의 오름차순으로 정열함
            profiles.Sort(
                (profile1, profile2) =>  { return profile1.Height - profile2.Height;  }
            );

            // 3단계 - 출력함
            foreach(var profile in profiles)
                Console.WriteLine("{0}, {1}", profile.Name, profile.Height);

            Console.ReadLine();
        }
    }

 

 

예제 2 - LINQ 문을 사용하여 프로그램 작성

 

키가 175 미만인 데이타만을 골라서 새 컬렉션으로 추출하는 프로그램

    class Profile
    {
        public string Name { get; set; }
        public int Height { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Profile[] arrProfile = {
                                       new Profile{Name = "이순신", Height=210},
                                       new Profile{Name = "강감찬", Height=169},
                                       new Profile{Name = "을지문덕", Height=175},
                                       new Profile{Name = "세종대왕", Height=183},
                                       new Profile{Name = "안창호", Height=159},
                                       new Profile{Name = "연개소문", Height=172}
                                   };

            // 1단계 - 키가 175 미만인 데이타를 추출함
            var profiles = from profile in arrProfile
                           where profile.Height < 175
                           orderby profile.Height ascending
                           select profile;

            // 2단계 - 출력함
            foreach (var profile in profiles)
                Console.WriteLine("{0}, {1}", profile.Name, profile.Height);

            Console.ReadLine();
        }
    }


예제3 - select 문의 분석


select 절은 다음과 같이 사용하면 됩니다.

var profiles = from profile in arrProfile
            where profile.Height < 175
            orderby profile.Height ascending
            select profile;

위의 예에서 var 형식으로 선언된 profiles 의 실제 형식이 궁금할 겁니다. C# 컴파일러가 var 형식을 LINQ 쿼리식이 반환할 결과 형식에 맞춰 알아서 컴파일 해 주기는 하지만, 실제로 var 가 어떤 형식으로 치환되는지를 알아둘 필요가 있습니다. LINQ 질의 결과는 IEnumerable<T> 로 치환되는데, 이 형식 매개변수 T는 select 문에 의해 결정됩니다. 


예를 들어 위 LINQ 쿼리식은 배열로부터 175 미만인 Profile 객체를 골라내는데, 그 결과는 IEnumerable<Profile> 형식이 됩니다. 다음과 같이 select 문에서 Profile 객체 전체가 아닌 Name 프로퍼티만 추출하면 profiles는 IEnumerable<string> 형식으로 컴파일됩니다.

var profiles = from profile in arrProfile
            where profile.Height < 175
            orderby profile.Height ascending
            select profile.Name;

추가적으로 select 문은 무명 형식(Anonymous type)을 이용해서 다음과 같이 새로운 형식을 만들어 낼 수도 있습니다.

var profiles = from profile in arrProfile
            where profile.Height < 175
            orderby profile.Height ascending
            select new { Name = profile.Name, InchHeight = profile.Height * 0.393 };

전체 소스

    class Profile
    {
        public string Name { get; set; }
        public int Height { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Profile[] arrProfile = {
                                       new Profile{Name = "이순신", Height=210},
                                       new Profile{Name = "강감찬", Height=169},
                                       new Profile{Name = "을지문덕", Height=175},
                                       new Profile{Name = "세종대왕", Height=183},
                                       new Profile{Name = "안창호", Height=159},
                                       new Profile{Name = "연개소문", Height=172}
                                   };

            // 1단계 - 키가 175 미만인 데이타를 추출함
            var profiles = from profile in arrProfile
                           where profile.Height < 175
                           orderby profile.Height ascending
                           select new { Name = profile.Name, InchHeight = profile.Height * 0.393 };

            // 2단계 - 출력함
            foreach (var profile in profiles)
                Console.WriteLine("{0}, {1}", profile.Name, profile.InchHeight);

            Console.ReadLine();
        }
    }



 

예제4 - where 조건에 and, or 연산자 사용하기 / 여러개의 데이타 원본에 질의하기

 

LINQ 쿼리식은 데이타 원본에 접근하기 위해 from 절을 사용합니다. 여러개의 데이타 원본에 접근하려면 from 절을 중첩해서 사용하면 됩니다.

 

foreach 문을 중첩해서 사용하는 것처럼 말입니다.

 

다음의 클래스는 각 학년별, 학급별, 점수를 나타내며, 과목별 점수를 담기 위해 Score 필드를 배열로 선언했습니다.

    class GradeClassScore
    {
        public int Grade { get; set; }
        public string ClassName { get; set; }
        public int[] Score { get; set; }
    }

 

그리고 이 클래스를 바탕으로 배열 하나를 다음과 같이 선언했습니다.

            GradeClassScore[] arrClass = {
                                             new GradeClassScore(){Grade = 1, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 1, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 1, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 1, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 1, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
                                             new GradeClassScore(){Grade = 2, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 2, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 2, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 2, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 2, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
                                             new GradeClassScore(){Grade = 3, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 3, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 3, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 3, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 3, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}}
                                         };

 

이제 준비는 마쳤습니다. 위 배열에서 1학년 중에서 점수가 60점 미만인 학급과 과목 점수를 중첩 from 절을 이용해서 뽑아 보겠습니다. 그리고 여기서 한가지 팁을 더 알려 드리자면 where 절에 and, or 를 포함 시킬 수 있습니다. 즉 and => &&, or => || 를 사용하시면 됩니다.

            var classes = from c in arrClass
                            from s in c.Score
                            where s < 60 && c.Grade == 1
                            orderby s
                          select new { c.ClassName, Lowest = s };

전체 소스

    class GradeClassScore
    {
        public int Grade { get; set; }
        public string ClassName { get; set; }
        public int[] Score { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            GradeClassScore[] arrClass = {
                                             new GradeClassScore(){Grade = 1, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 1, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 1, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 1, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 1, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
                                             new GradeClassScore(){Grade = 2, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 2, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 2, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 2, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 2, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}},
                                             new GradeClassScore(){Grade = 3, ClassName = "연두반", Score = new int[]{10, 20, 30, 40, 50}},
                                             new GradeClassScore(){Grade = 3, ClassName = "분홍반", Score = new int[]{65, 75, 85, 95, 100}},
                                             new GradeClassScore(){Grade = 3, ClassName = "파랑반", Score = new int[]{68, 28, 38, 48, 58}},
                                             new GradeClassScore(){Grade = 3, ClassName = "노랑반", Score = new int[]{83, 84, 85, 86, 86}},
                                             new GradeClassScore(){Grade = 3, ClassName = "보라반", Score = new int[]{87, 87, 87, 87, 87}}
                                         };

            var classes = from c in arrClass
                            from s in c.Score
                            where s < 60 && c.Grade == 1
                            orderby s
                          select new { c.ClassName, Lowest = s };

            foreach(var c in classes)
                Console.WriteLine("낙제 : {0} ({1})", c.ClassName, c.Lowest);

            Console.ReadLine();

        }
    }

 

 

posted by 따시쿵