책이고 뭐고
이거보면서 링크 보면 끝날듯..

근데 인간적으로 MSDN에 써잇는건 말이 너무 이상해. ㅠㅠㅋ
by 피요히코~ 2010. 12. 9. 16:04
XML형식의 string을 XDocument.Parse(string) 해서 XDocument로 만든후에

그 XML에서 특정 element만 가져오고 싶으면
(from node in XDocument.Descendants("elementName") select node)

이렇게 하면 여러개의 XElement가 나올것이고

이걸 만약 List<XElement> 형식으로 바꾸고 싶으면
(from node in XDocument.Descendants("elementName") select node).ToList<XElement>();
하면 됩니다.

만약 이걸 특정 attribute를 가지고 Dictionary형태로 만들고 싶으면
Dictionary<string,string> 인데 attribute중 class가 key고 name이 value라면
(from node in XDocument.Descendants("elementName") select node).ToDictionary( t => t.Attribute("class").value, t => t.Attribute("name").value);


요로케..

음.. 이게 LINQ인가... ;;;


by 피요히코~ 2010. 12. 9. 09:47
이제 본격적으로 시작해 보죠.

앞의 내용들을 다 하고 나면
LINQ to SQL 클래스 만들때 넣은 이름+Context라는 클래스를 사용할수 있어요.

먼저 간단한 select부터 해볼께요.


             using (DataClasses1DataContext db = new DataClasses1DataContext())
            {
                var r01 = from x in db.LINQTEST
                          where x.age > 20
                          select x;

                foreach (var x in r01)
                {
                    Console.WriteLine(x.name);
                }
            }

LINQ to SQL 클래스를 쓰는거 말고는
전에 했던 LINQ to Object와 별 차이가 없네요

위 코드는
LINQTEST 테이블에서 age가 20보다 큰 x를 가져와서
x의 name을 출력하는 거에요.

이렇게 나오네요.

뭐. 설명하고 자시고 할것도 없네요.

이번에는 insert를 해볼께요.
먼저 코드
            using (DataClasses1DataContext db = new DataClasses1DataContext())
            {
                //객체를 만듭니다
                LINQTEST newData = new LINQTEST();
                //데이터를 넣습니다
                newData.name = "피요히코";
                newData.age = 30;
                newData.comment = "추가된 데이터입니다.";
                //변경된 내용을 반영합니다.
                db.LINQTEST.InsertOnSubmit(newData);
                db.SubmitChanges();
            }

순서는
1. insert할 객체를 만들고
2. 데이터를 넣고
3. 적용시킨다

입니다.

주의해야 할건
1. 테이블에는 항상 기본키가 잡혀 있어야 한다.
2. 변경내용은 SubmitChanges()를 해야 적용된다.
입니다.

LINQ to SQL 클래스를 사용하면 인텔리센스를 통해서 table과 column등에 접근할수 있으므로
정말 편하게 쿼리를 날릴수 있어요.

코드 자체는 어렵지 않으니
update와 delete 하는건 코드만 보고 넘어가도 될꺼 같네요.
(몇몇 중요해 보이는 부분은 주석으로 설명을 해둘꼐요)

update

            using (DataClasses1DataContext db = new DataClasses1DataContext())
            {
                var searchItem = (from x in db.LINQTEST
                                  where x.name == "피요히코"
                                  select x).SingleOrDefault();
                //Single()로 검색할경우 해당값이 없으면 Exception발생
                //SingleOrDefault()의 경우는 값 없을때 Null 리턴

                if (searchItem != null)
                {
                    //searchItem이 null이 아닌경우 comment를 변경
                    searchItem.comment = "변경되었어요.....";
                }

                //변경내용 확인
                var r01 = (from x in db.LINQTEST
                           where x.name == "피요히코"
                           select x).SingleOrDefault();
                Console.WriteLine(r01.comment);
            }

delete
            using (DataClasses1DataContext db = new DataClasses1DataContext())
            {
               var searchItem = (from x in db.LINQTEST
                                  where x.name == "피요히코"
                                  select x).SingleOrDefault();

                //삭제
                db.LINQTEST.DeleteOnSubmit(searchItem);
                db.SubmitChanges();

                //결과확인
                var searchItem2 = (from x in db.LINQTEST
                                  where x.name == "피요히코"
                                  select x).SingleOrDefault();
                if (searchItem2 == null)
                {
                    Console.WriteLine("지워졌다. ㅠㅠ");
                }
                else
                    Console.WriteLine(searchItem2.name);
            }

출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 21:05

이번에는 (좀더 많이 쓸수 있어 보이는)
LINQ to ADO.NET에 대해 봐볼께요
(LINQ to SQL이라고 해도 될듯한..)

이녀석은 일단 몇가지 선행작업이 필요해요.

일단 test해볼 테이블을 하나 만들었습니다.



그리고 테이블에 간단한 데이터를 몇개 넣어놨어요.


데이터가 뭐 이러냐 싶겠지만 pass....

비주얼스튜디오에서 서버탐색기를 열어서
DB를 연결시켜 줍니다.


그다음에
새항목을 추가 해야 되는데요.
LINQ to SQL 클래스를 추가해 줘야 해요.
이름은 MS에서 추천해주는 이름으로~

그러면
DataClasses1.dbml 파일과 DataClasses1.designer.cs 파일이 생겨요.
그리고 DataClasses1.dbml이 열려 있는데.
그 화면에
쓰고 싶은 테이블이나 프로시저 등을 서버탐색기에서 끌어다 놓으면 됩니다.

전 아까 만들어둔 LINQTEST 테이블을 끌어다 놓을께요.
(끌어 놓을때 경고창이 하나 떠요
 연결문자열을 구성파일에 저장할꺼냐 말꺼냐.
 아니요~ 하면 됩니다
 대신 app.config에서 connectionString에 pwd를 추가해 주셔야 해요. )

여기까지 했으면 이제 준비가 끝났네요...



출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 20:51
LINQ to Object 마지막입니다.
(사실 내용이 Object에만 해당되는건 아니죠.. -ㅁ-;;)

이번엔 Take와 Skip,그리고 TakeWhile, SkipWhile에 대해볼께요.

예제는 너무나도 간단하네요.


            int[] nums = { 10, 9, 8, 7, 5, 6, 4, 3, 2, 1 };

            var r01 = nums.Take(3);
            var r02 = nums.Skip(3);
            var r03 = nums.TakeWhile(x => x > 5);
            var r04 = nums.SkipWhile(x => x > 5);

간단하지만 (저는)헷깔릴수 있으니 잘 봐야 합니다. ㅋ
일단 nums를 보면 숫자 순서가 7,6,5 가 아니라 7,5,6 입니다.

첫번째로 Take(3)을 하면 그냥 앞에서 3개만 가져옵니다.
두번째로 Skip(3)을 하면 반대로 뒤에서 3개만 가져오죠

While이 좀 헷깔리는데요
r03에서 TakeWhile(x => x > 5)를 하면
x가 5보가 큰 녀석들을 가져오는건데.
이게 (루프를 돌겠죠?) 5보다 큰녀석을 다 가져오는게 아닙니다.
10,9,8,~~ 돌면서 5보다 큰 녀석을 찾는데
보면.. 7 까지는 5보다 크지만 그 다음에 5는 5보다 크지 않죠.
그럼 거기서 끝납니다.
그 다음에 6이라는 숫자가 5보다 크지만.
신경 안써요.
그냥 끝나버리는거에요.

SkipWhile도 비슷해요.
5보다 크면 skip해버리는데
10~7까지 스킵하고. 5부터 출력을 하는데. 그 다음수인 6이 5보다 큰거 따위 신경 안쓰죠.


그럼 이번에는
Non-Generic 타입을 사용하는걸 봐볼께요.
Non-Generic 타입은 바로 사용은 못합니다.

코드를 보면
일단 ArrayList를 선언하고 값을 몇개 넣습니다.
            ArrayList src = new ArrayList();
            for (int i = 0; i < 10; i++)
            {
                src.Add(i + 1);
            }

그 다음에
                      var r01 = from x in src
                      where x > 3
                      select x;


이렇게 해주면 바로 오류가 납니다.
오류 내용은

소스형식 'System.Collections.ArrayList'에 대해 구현된 쿼리 패턴을 찾을 수 없습니다.
'Where'을(를) 찾지 못했습니다. 범위 변수 'x'의 형식을 명시적으로 지정하십시오.

라고 나오네요
ArrayList를 사용하고 싶으면
casting을 해줘야 해요

                      var r01 = from x in src.Cast()
                      where x > 3
                      select x;

요렇게요.
그럼 결과값이 잘 나옵니다.

출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 20:16

앞에 포스팅했던 LINQ to Object 이어서 줄줄 입니다.

이번에는 간단하게 SubQuery에 대해 볼께요.
그냥 쿼리 안에 쿼리가 있는건데
T-SQL에서도 조건에 쿼리를 붙이고 하는걸 LINQ로 하면요

           string[] names = { "Tom", "Bill", "Harry", "June", "Mary", "Jay" };

            var r01 = from x in names
                      where x.Length == (
                                          from y in names
                                          orderby y.Length
                                          select y).First().Length
                      select x;

            foreach (var x in r01)
            {
                Console.WriteLine(x);
            }

그냥.
names에서 x라는 녀석을 가져오는데

(여기부터가 subQuery죠)
(다시)
names에서 y라는 녀석을 가져오는데
y의 길이로 정렬을 해서
가져온후에
첫번째 녀석(First())의 길이를 가져온다    << 이녀석이 x의 조건이 되는거에요
(subQuery끝)

이 길이의 x를 가져온다...

가 되는거죠.
정렬에 따로 말이 없으면 ascending이므로
Tom인지  Jay인지는 모르겠지만 암튼 둘중 하나가 First가 되겠죠.
그녀석의 길이와 같은 x를 가져오는것이니

출력값은????
이렇게 나오네요.

이번엔 into에 대해 살펴보죠(헥헥헥)
into키워드는 group, join, select 같은 임시 저장 식별자를 만들어 주는건데요.

예제를 보는게 이해가 빠를꺼에요.

                      var r01 = from x in names
                      where x.Contains("a")
                      select x
                          into subSet
                          where subSet.Length > 4
                          orderby subSet
                          select subSet;


(제가 이해한게 맞다면)
into는 (단어 뜻 그대로)
into키워드 앞의 결과를 뒤에 넣어주는거죠
코드를 보면
x를 subSet에 into했네요.
그 다음에 subSet을 가지고
조건을 걸어서(정렬조건도)
select~

그럼 결과는 어떻게 나올까요?
이름에 "a"가 들어간 놈을 찾아서 나온 결과들중에서(이게 x)
길이가 4 이상인 녀석들을 select하니까.

이렇게 나오네요.
(아마도 x에는 Harry랑 Mary랑 Jay가 있었겠죠)

into를 쓸때 주의할껀
into를 쓴 후에는
원본 x에 접근을 할수가 없다는 거에요.

원본 x에도 접근하고 싶다면
into가 아니라 let을 쓰면 되요
let키워드는 부분결과 집합을 만들어서 쿼리내에서 참조 하는겁니다

                      var r01 = from x in names
                      let temp = x.Replace("a", "")
                      where x.Contains("a")
                      select new
                      {
                          Original = x,
                          Change = temp
                      };

출력값은

간단하네요~

출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 19:49

LINQ to Object는

IEnumerable<T> interface가 구현된 어떤 Object에서도 사용이 가능합니다.

Non-Generic 타임은 Cast를 통해 쿼리가 가능합니다.

예제를 보죠.

private static void QuetyTest()
{
     string[] names = { "Tom", "Bill", "Harry", "June", "Mary", "Jay" };

     var r01 = from x in names
          where x.Contains("a")
          orderby x.Length
          select x;

     foreach (var x in r01)
     {
          Console.WriteLine(x);
      }
}

형식은 sql을 해봤다면 눈에 살짝 들어올꺼에요.
3번째 줄에서는 사용할 data를 만들었어요(이름들이죠)

5번째 줄~8번째줄에서 data를 가져오는데요
names는 사용할data
x는 그 data에서 한녀석(?)을 의미해요.
(위의 names에 있는 이름들 하나하나 같은거죠.... 음....)

where 뒤쪽이 이제 가져올 data에 대한 조건을 의미하고
Contains("a")는 "a"가 포함되어 있는지 여부를 확인하는 겁니다.

orderby 는 정렬조건인데
orderby x.Length는 x의 길이로 정렬을 한다는 거죠(참 쉽죠잉~  )

이렇게 하면 r01에 해당 data가 들어가 있겠죠.

그 다음에 출력을 해보면
이렇게 나와요.
(이름에 "a"가 들어가 있는 녀석들만 나오는거죠.)

그럼 이제
앞에 포스팅 했던 글에서 말했던
지연실행에 대해 볼께요.

            var numbers = new List();
            numbers.Add(1);

            var r01 = numbers.Select(x => x * 10);

            numbers.Add(2);

            foreach (var x in r01)
            {
                Console.WriteLine(x);
            }

2번째 줄에서 numbers에 1을 넣고.
3번째 줄에서 numbers.select를 해서 값을 가져옵니다.
가져올 값 x는 x*10을 해서요

그러면 r01에는 10이 들어가겠죠?

그 다음에 numbers에 2를 넣어줍니다.

그리고 출력을 합니다.

결과가 어떻게 나올까요?
10 이 나와야 할꺼 같네요.

근데 10과 20이 출력 됐네요...

10과 20이 출력된 이유는 바로
LINQ가 지연실행되기 때문입니다.
1을 넣고 r01에 1*10을 넣었지만.

그때 쿼리가 실행된게 아니라 데이터가 열거되는 시점인
5번째줄~8번째 줄때 쿼리가 실행됐기 때문에
numbers.Add(2)가 포함된 값이 출력된것이죠.

이걸 잘 염두해 두지 않으면
정말로 원치 않는 엉뚱한 결과가 나올수도 있어요.

하지만 (역시 앞에서 말했던 건데요)
이걸 바로 실행되게 할수도 있어요

var r01 = numbers.Select(x => x * 10).ToList();

이렇게 해주면
바로 쿼리가 실행되서
원하는(이걸 원한다면 말이죠) 값이 출력 되겠죠.

글이 너무 길어지면 보기 싫으니
나머지 예제들은 뒤로 보낼께요

출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 19:28

먼저 주요 연산자를 살펴볼께요.

(출처는 김수영님의 주말특강 PPT자료입니다.... )

연산자들이 딱 보면 대충 뭐에 쓰는지 다 감이  오네요.
이 연산자들은
LINQ to Object이건 XML이건 다 적용이 됩니다. 

예제는 다음 LINQ to Object에서 보여드릴께요

LINQ를 사용할때.
꼭 염두해둬야 할께 있는데요
LINQ는 지연실행(Deferred Execution) 된다는 겁니다.

생성시에 쿼리가 실행되는게 아니라 데이터가 열거될때 실행된다는 건데요
이게 왜 중요한지는 뒤의 예제에서 같이 보여드릴꼐요.

단 예외적으로 지연실행 되지 않는 경우가 있는데
- First, Count같은 스칼라 값이나 단일 element를 반환할때
- ToArray, ToList, ToDictionary, ToLookup 실행때 입니다.
(원본 데이터를 처리하는게 아니라. Copy를 할때)

출처?는 김수영MVP님의 주말특강입니다
by 피요히코~ 2009. 4. 26. 19:20
LINQ란 무엇인지 먼저
MSDN의 설명을 간단하게 보면요

업데이트: 2007년 11월

LINQ(통합 언어 쿼리)는 개체와 데이터 간 격차를 줄이므로 Visual Studio 2008 및 .NET Framework 버전 3.5에서 획기적인 혁신입니다.

일반적으로 데이터에 대한 쿼리는 컴파일 시 형식 검사 또는 IntelliSense 지원 없이 단순 문자열로 표현됩니다. 게다가 각 데이터 소스 형식에 대해 SQL 데이터베이스, XML 문서, 다양한 웹 서비스 등 다양한 쿼리 언어를 배워야 합니다. LINQ는 C# 및 Visual Basic에서 쿼리를 고급 언어 구문으로 만듭니다. 언어 키워드 및 친숙한 연산자를 사용하여 개체에 대한 강력한 형식의 컬렉션에 대해 쿼리를 작성합니다. 다음 그림에서는 전체 형식 검사 및 IntelliSense 지원을 사용하여 C#에서 SQL Server 데이터베이스에 대해 부분적으로 완료된 LINQ 쿼리를 보여 줍니다.

Intellisense를 사용한 LINQ 쿼리

Visual Studio에서는 Visual Basic 또는 C#을 사용하여 SQL Server 데이터베이스, XML 문서, ADO.NET 데이터 집합 및 IEnumerable 또는 제네릭 IEnumerable<(Of <(T>)>) 인터페이스를 지원하는 개체의 컬렉션에 대한 LINQ 쿼리를 작성할 수 있습니다. ADO.NET Entity Framework에 대한 LINQ 지원도 계획되어 있으며 여러 웹 서비스 및 다른 데이터베이스 구현에 대한 LINQ 공급자도 타사에 의해 개발되고 있습니다.

새 프로젝트의 LINQ 쿼리나 기존 프로젝트의 LINQ가 아닌 쿼리를 함께 사용할 수 있습니다. 단, 프로젝트에서 .NET Framework 버전 3.5를 대상으로 해야 합니다.

(출처 : MSDN)

이렇게 되어 있네요.
LINQ는 Language 레벨에서 통합된 질의(Query)를 가능케 하는 문법(?) 이라고 하면 되지 않을까 싶어요
(제가 이렇게 알고 있거든요. --ㅋ)

LINQ를 사용하면
코드에서 오류등을 표시해 주기 때문에 오류를 줄일수 있어요.
(그냥 쌩으로 쿼리를 날리면 string으로 넘어가니. 작성 시점에서 이제 맞게 작성 됐는지 알기가 힘들잖아요.
 물론 미리 한번 확인을 해보고 쓰면 되긴 하겠지만요. ㅎㅎ)

LINQ는
LINQ to Object
LINQ to DataSets
LINQ to SQL
LINQ to Entities
LINQ to XML

이 있는데

저는 Object와 DataSet, SQL, XML에 대해 정리해 볼께요.
by 피요히코~ 2009. 4. 26. 19:13
| 1 |