'LINQ'에 해당되는 글 3건

Programming/.NET

배열이나 컬렉션에 들어간 요소를 순회하는 고전적인 방법중 하나는 foreach를 이용하는 것입니다.

 

List<Member> li = new List<Member{
    new Member { Name = "홍길동"Age = 40, BirthDay=DateTime.Parse("1978-01-28") },
    new Member { Name = "홍길순"Age = 21, BirthDay=DateTime.Parse("1997-05-16") },
    new Member { Name = "홍길남"Age = 38, BirthDay=DateTime.Parse("1980-03-06") },
    new Member { Name = "홍길영"Age = 19, BirthDay=DateTime.Parse("1999-11-20") },
    new Member { Name = "홍길석"Age = 27, BirthDay=DateTime.Parse("2003-08-04") }
};

foreach (Member m in li) {
    Console.WriteLine(m.Name);
}

 

이 상태에서 만약 나이가 20세 이상인 사람만을 추려내려면 if문을 추가할 수 있을 것입니다.

 

foreach (Member m in li) {
    if (m.Age > 20)
        Console.WriteLine(m.Name);
}

 

LINQ(Language Integrated Query)는 이러한 열거작업에 대한 확장구문으로서 SQL 쿼리와 비슷한 문법체계를 가지고 있습니다. 여기에서는 예제로 LIst형식의 컬렉션만을 다루고 있지만 컬렉션뿐만 아니라 XML이나 DB와의 연동에서도 LINQ가 사용되고 있습니다. 이렇게 다양한 곳에서 LINQ가 사용된다는 것은 LINQ문법만 익히면 일관된 방식으로 데이터를 쿼리할 수 있다는 것을 뜻합니다.

 

우선 간단하게 LINQ를 통해 전체를 열거하는 부분부터 살펴보겠습니다.

 

var ret = from Member in li
            select Member;

foreach (Member m in ret)
        Console.WriteLine(m.Name);

 

LINQ에서 select는 yield return과 같습니다. yield return은 IEnumerable<T>형식을 반환하므로 var ret는 IEnumerable<Member> ret로 바뀔 수 있습니다.

 

예제에서는 foreach에서 Name값을 가져오는데 이는 LINQ의 select에서도 처리될 수 있습니다.

 

var ret = from Member in li
            select Member.Name;

foreach (string m in ret)
        Console.WriteLine(m);

 

출력되는 값에 특정 포멧을 적용해야 한다면 select에서 익명타입을 구현하면 됩니다.

 

var ret = from Member in li
            select new { Name = Member.Name, BirthDay = Member.BirthDay.ToString("yyyy년MM월dd일") };

foreach (var m in ret)
        Console.WriteLine(m.Name + " : " + m.BirthDay);

 

LINQ에서 where를 이용하면 조건을 필터링할 수 있습니다.  여기에는 bool형식의 구문이 와야 합니다.

 

var ret = from Member in li
          where Member.Age > 20
          select Member;

foreach (var m in ret)
        Console.WriteLine(m.Name + " : " + m.BirthDay);

 

요소를 정렬하기 위해서는 orderby를 사용하며 IComparable 인터페이스가 구현된 타입이어야 합니다.

 

var ret = from Member in li
            orderby Member.Name descending
            select Member;

foreach (var m in ret)
        Console.WriteLine(m.Name);

 

orderby에서 descending는 내림차순, ascending는 오름차순입니다.

 

이외에도 서로 다른 컬렉션을 연결하는 join이나 특정 값으로 그룹핑하는 group by절등 다양한 구문이 존재하는데 여기서 몇몇 특징적인 기능의 경우에는 IEnumerable<T>의 확장메서드형태로 제공하는 것들이 있습니다.

 

예들 들면 select같은 경우

 

IEnumerable<Member> im = li.Select((em) => em);
foreach (Member m in im)
    Console.WriteLine(m.Name);

 

위와 같은 형태로 구현할 수 있도록 되어 있는데, 이러한 확장 메서드는 Select외에 Where나 OrderBy등 수십여가지의 메서드가 존재하니 필요할때 적절한 메서드를 사용하면 됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET MVC] AJAX  (0) 2017.12.22
[C#] Assembly  (0) 2017.12.13
[C#] LINQ  (0) 2017.12.05
[C#] 문자열 보간 ($)  (0) 2017.11.28
[C#] ArrayList  (0) 2017.11.14
[C#] 선택적 매개변수  (0) 2017.11.07
0 0
Programming/.NET

 1. XML 직렬화 (XmlSerializer)

 

XmlSerializer는 XML 데이터에서 원하는 값에 대해 특정 클래스(Class)로 CLR개체를 생성하는 직렬화를 수행할 수 있습니다.

 

우선 아래와 같이 간단한 클래스 하나를 추가합니다.

 

[XmlRoot(ElementName = "book")]
public class book_titleAndgenre
{
    [XmlElement(ElementName = "title")]
    public string title;
    [XmlElement(ElementName = "genre")]
    public string genre;
}

 

이 클래스는 title과 genre속성에 ElementName 특성을 추가해 XML의 어떤 요소값이 대상이 되는지를 알려주고 있습니다. 이렇게 해두면 샘플 XML에서 book요소를 기준으로 title과 genre값을 가져와 클래스로 직렬화 할 것입니다.

 

NameTable nt = new NameTable();
object book = nt.Add("book");

xrs.NameTable = nt;

XmlSerializerFactory xsf = new XmlSerializerFactory();

using (XmlReader reader = XmlReader.Create(xml_file, xrs)) {
    while (reader.Read()) {
        if (reader.NodeType == XmlNodeType.Element && book.Equals(reader.LocalName)) {
            XmlSerializer xs = xsf.CreateSerializer(typeof(book_titleAndgenre));
            book_titleAndgenre bt = (book_titleAndgenre)xs.Deserialize(reader.ReadSubtree());
            Response.Write(bt.title + ":::" + bt.genre + "<br />");
        }
    }
}

 

NameTable에 book요소를 추가하여 XML데이터를 검색합니다. XML데이터 순회도중 book에 해당하는 요소를 만나면 우선 위에서 생성한 클래스형태의 직렬화개체를 생성하고 ReadSubtree 메소드를 통하여 하위 모든 요소를 가져와 역직렬화를 통해 해당 클래스에 속성을 추가하게 됩니다.

 

ReadSubtree 메소드는 Read 메소드와 비슷하게 현시점에서 하위 모든 XML을 순회하도록 하지만 Read는 bool 타입을 반환하는 반면 ReadSubtree는 새로운 XmlReader개체를 생성합니다.

 

XmlSerializerFactory 클래스의 CreateSerializer 메소드는 Type개체를 인자값으로 받는데 이 인자로 전달한 개체는 어셈블리형태로 생성될 수 있는 개체여야 하기 때문에 직렬화의 대상이 클래스가 되는 것입니다.(참고로 클래스로 직렬화되는 대상은 public 속성만을 대상으로 합니다.)

 

 2. Linq를 사용한 CLR 개체생성

 

CLR개체를 생성하는 거라면 Linq를 사용해 위에서 보다 더 간단히 구현할 수 있습니다.

 

string xml_file = Server.MapPath("books.xml");

XDocument xd = XDocument.Load(xml_file);

var titleAndgenre = from book in xd.Descendants("book")
                    select new book_titleAndgenre
                    {
                        title = book.Element("title").Value,
                        genre = book.Element("genre").Value
                    };

foreach (book_titleAndgenre bt in titleAndgenre)
    Response.Write(bt.title + ":::" + bt.genre + "<br />");

 

Linq를 사용하는 방법은 실제 읽어들인 XML에서 select 구문으로 원하는 부분의 데이터를 읽어오도록 처리합니다. 위에서 보여진 예제와는 사뭇 다른데 특정 데이터값만을 대상으로 하는 Linq쿼리를 직접 다루게 되므로 직렬화나 역질화에 필요한 클래스를 사용하지 않습니다.

 

그렇다 보니 기존 클래스와의 타입 대조절차가 빠지게 되므로 개체생성 대상이 되는 클래스조차 별다른 특성없이 간단하게 작성될 수 있습니다.

 

public class book_titleAndgenre
{
    public string title;
    public string genre;
}

 

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] XML - 5  (0) 2016.02.18
[ASP.NET] XML - 4  (0) 2016.02.11
[ASP.NET] XML - 3  (0) 2016.02.01
[ASP.NET] XML - 2  (0) 2016.01.26
[ASP.NET] XML - 1  (0) 2016.01.18
[ASP.NET] Command Object  (0) 2016.01.13
0 0
Programming/.NET
SQL 데이터베이스에 직접적으로 연결하여 쿼리를 처리하는 SqlDataSource 컨트롤과는 달리 LinqDataSource 는 대상이 되는 DB 데이터를 객체화 하여 LINQ 를 통해 처리할 수 있도록 하는 컨트롤입니다.

LinqDataSource 컨트롤을 사용하기 전에 우선 LINQ to SQL 을 통해 다루고자 하는 데이터의 Data Context 클래스를 생성하여야 합니다.

프로젝트에서 마우스 오른쪽 버튼을 눌러 Add -> New Item 을 선택합니다.


Add New Item 화면에서 왼쪽 Data 카테고리를 선택하고 오른쪽 LINQ to SQL Classes 항목을 선택한 뒤 Add 버튼을 눌러줍니다. 이때 이름(Name)은 원하는대로 지정해도 됩니다.

위 단계를 거치고 나면 프로젝트에 .dbml 파일이 생성되고 해당 디자이너 화면이 보여질 것입니다. 이제 데이터 서버에 연결하여 대상이 될 테이블을 가져오도록 하겠습니다.

Visual Studio 의 Server Explorer 에서 Data Connections 을 우클릭 한 다음 Add Connection 메뉴를 선택합니다.


Server Name 에 대상 서버이름이나 IP 등을 입력하고 Log on to the server 에 접속가능한 계정을 설정합니다. 그러면 Select or enter a database name 에 사용가능한 DB 목록이 보여질 것입니다. 해당 목록에서 다루고자 하는 대상이 있는 DB를 선택하고 OK 버튼을 눌러줍니다.


Server Explorer 화면에 방금전 등록한 DB 가 연결되었음을 확인할 수 있습니다. 해당 DB 에서 원하는 테이블을 dbml 디자이너 화면에 끌어다 놓습니다.

dbml 파일을 저장하고 LinqDataSource 를 사용하고자 하는 aspx 페이지의 디자이너화면에서 Visual Studio Toolbox 의 Data 카테고리 안에 있는 LinqDataSource 컨트롤을 마우스로 끌어다 놓습니다.


LinqDataSource 컨트롤의 SmartTag 를 클릭하여 'Configure Data Source' 항목을 선택합니다.


이 화면에서 Choose your context object 에 있는 항목중 데이터소스로 활용하고자 하는(이전 단계에서 생성한) 데이터 컨텍스트 객체를 선택할 수 있으며 여기에는 System.data.Linq.DataContext 클래스 에서 파생된 객체항목이 나열됩니다. 참고로 System.data.Linq.DataContext 클래스는 LINQ to SQL 에 의해 생성된 데이터 컨텍스트 클래스에 해당됩니다.

▶ <그림 1-1>

위 화면은 Choose a Context Object 화면에서 원하는 컨텍스트 객체를 선택하고 'Next' 버튼을 누른 뒤 화면으로 여기에서는 이전에 선택한 객체의 데이터 항목중 실제 바인딩하고자 하는 항목을 선택할 수는 화면입니다. 실제 위 화면에 나오는 항목은 샘플데이터베이스(AdventureWorks2012)의 Person.Person 테이블의 열항목인데 만약 대상 클래스가 DataContext 에서 파생된 클래스가 아닌 다른 클래스의 형태라면 해당 클래스에 있는 배열등의 속성항목등을 볼 수 있게 됩니다.

<그림 1-1>에서 특정 필드를 선택하면 <코드 1-1>과 같이 선택한 필드를 포함한 LINQ 쿼리가 생성될 것입니다.
<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="Webtest.DataClasses1DataContext" EntityTypeName="" Select="new (Title, FirstName, MiddleName)" TableName="Persons"></asp:LinqDataSource>
▶<코드 1-1>

실제 <코드 1-1>의 LinqDataSource 를 GridView에 바인딩해 보면 다음과 같은 결과를 볼 수 있습니다.
<asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSource1"></asp:GridView>
1 0
1
블로그 이미지

클리엘