태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.
   情  
Front Page
Tag | Location | Media | Guestbook | Admin   
 
'Web Development/ASP.NET'에 해당하는 글(11)
2009.09.08   [ASP.NET] Calendar Extender의 줄바꿈 문제 해결하기
2009.05.06   ASP.NET VisualStudio의 localhost에서 FireFox 속도 저하현상 해결 (1)
2009.04.03   ASP.NET 중첩 마스터 페이지의 FindControl
2009.03.05   ASP.NET $get(), $find의 차이점 (1)
2009.02.02   ASP.NET Ajax Accordion Control
2008.12.25   ASP.NET Ajax ModalPopup UpdateProgress
2008.12.07   ASP.NET Ajax Extensions
2008.12.05   ASP.NET 3.5 GridView에서 Ajax Pop-up을 이용한 상세정보 표시 (2)
2008.12.04   ASP.NET 3.5
2008.11.27   ASP.NET 3.0 - LINQ


[ASP.NET] Calendar Extender의 줄바꿈 문제 해결하기

Calendar Extender를 사용할 때 발생하는 문제 하나 있는데요, 다음 그림을 통해 설명 드리도록 하겠습니다.

<asp:TextBox ID="date" runat="server" />
<AC:CalendarExtender ID="ce" runat="server" TargetControlID="date" />
<asp:RadioButton ID="am" runat="server" GroupName="rbtSendAmOrPm" Text="오전" />
<asp:RadioButton ID="pm" runat="server" GroupName="rbtSendAmOrPm" Text="오후" />
<asp:TextBox ID="tbxSendHour" runat="server" /> 시
<asp:TextBox ID="tbxSendMinute" runat="server" /> 분

위 코드를 작성한 다음 실행하면 다음 화면이 나타납니다.

before

CalendarExtender의 Target Control을 선택하면 다음과 같은 화면으로 Line이 먹히는 것을 볼 수 있습니다.

calendar

아래는 Calendar Extender를 닫은 화면입니다.

after

이와 같은 문제를 해결하기 위해서는 다음과 같은 간단한 StyleSheet Code를 추가하시면 됩니다.

.ajax__calendar { display: inline; }

 

아래는 Style가 적용된 후 화면입니다.

calendarAfter

 

감사합니다.

Tag : ASP.NET

name    password    homepage
 hidden


ASP.NET VisualStudio의 localhost에서 FireFox 속도 저하현상 해결

VisualStudio(2005 또는 2008)를 사용하여, 웹어플리케이션을 실행하면 localhost로 실행이 되는데요. 이 때, firefox에서 속도가 상당히 저하되는 현상을 보이기도 합니다. 이 문제는 IPv6와 DNS에 관련되어 발생하는 문제입니다.

따라서 이문제를 해결하는 방법은 간단합니다. Firefox에서 IPv6 DNS를 꺼버리면됩니다.

  1. firefox 주소창에 about:config를 입력합니다.
  2. network.dns.disableIPv6를 찾습니다.
  3. 더블클릭하여 값을 true로 만듭니다.
  4. 문제가 해결되었는지 확인해봅시다.

또 다른 방법으로는 다음이 있다고 합니다. 문제가 되는 Windows파일을 삭제해버리는 방법으로서 문제의 원인을 없애버리는 것입니다.

  1. C:\WINDOWS\system32\drivers\etc 폴더로 이동합니다.
  2. hosts 파일을 삭제합니다.
  3. 문제가 해결되었는지 확인해봅시다.
Tag : ASP.NET
Commented by at 2011.08.13 00:12 신고  r x
오~ 실행하고 한참뒤에 켜지던게... 첫번째 방법그대로 하니.. 바로 뜨네요!

name    password    homepage
 hidden


ASP.NET 중첩 마스터 페이지의 FindControl

중첩 마스터 페이지의 경우, 마스터페이지의 컨트롤을 찾기위해서는 다음과 같이 최상단의 Master Page로 이동 후, 단계적으로 찾아 내려오는 과정이 필요합니다.

예를들어 마스터페이지가 2개 중첩된 경우, Master.Master을 이용하여 최상단 MasterPage로 이동하는 과정이 필요하며, 최상단에서 ContentPlaceHolder을 찾아서 단계적으로 하위로 이동하여 자신이 원하는 컨트롤을 찾아야합니다.

MasterPage : firstContentPlaceHolder
MasterPage : secontPlaceHolder
<asp:Label id="targetLabel" />
ASPX Page : ContentPage
 

위의 페이지 구조를 가지는 경우, ContentPage에서  targetLabel을 컨트롤 해야하는 경우, 먼저 다음과 같은 코드로 Label을 찾아야합니다.

- ASPX Content Page에서 targetLabel을 컨트를 하는 방법
Label
targetLabel = this.Page.Master.Master
    .FindControl("firstContentPlaceHolder")
    .FindControl("secondContentPlaceHolder")
    .FindControl("targetLabel")as Label;

targetLabel.Text = "Hello ASP.NET";

Tag : ASP.NET

name    password    homepage
 hidden


ASP.NET $get(), $find의 차이점

ASP.NET에서 ScriptManager가 페이지에 위치했을 때 자바스크립트에서는 $get()과 $find()를 사용할 수 있게 됩니다.

1.$GET()

$get는 docuemnt.getElementById와 element.getElementById 함수를 간단하게 사용할 수 있게 합니다. $get함수는 ASP.NET AJAX client sidle librarySys.UI.DomElement.getElementById와 관련이 있으며, 따라서 페이지에 ScriptManager을 위치시켰을 때에 비로소 사용할 수 있습니다. $get함수는 두가지 매개변수를 받습니다. 첫번째는 찾을 컨트롤의 id이며, 두번째는 선택적으로 사용가능한 '찾을 컨트롤이 포함된 부모 Element'입니다.

$get(id, element);

만약 디버깅 모드에서 $get함수를 찾아보면 다음과 같은 코드로 이루어져 있음을 알 수 있습니다.

function get(id, element)
{
        //  validation code that was removed

        if (!element) return document.getElementById(id);
        if (element.getElementById) return element.getElementById(id);

        //  manual DOM walk that was removed ...
    }

* 주의 : $get은 getElementById와 동일합니다. 따라서 서버컨트롤의 경우 ClientID를 $get()의 매개변수로 사용해야합니다. 한가지 더 참고할 점은, 특정 id를 가진 컨트롤을 찾을 필요없이, 해당 id를 적어주는 것만으로도 자바스크립트에서 해당 id를 갖는 컨트롤을 매핑시켜준다는 점입니다.
<span id="spanid">span text</span>
위의 코드에서는 아래의 코드가 작동합니다.(IE6, 7, FF 모두 가능)
alert(spanid.innerHTML);

2. $FIND() 

ASP.NET AJAX 컨트롤의 ID또는 BehaviorID로 해당 컨트롤을 찾을 수 있게합니다. 마찬가지로 2가지 매개변수를 받는데 첫번째는 찾을 ASP.NET AJAX 컨트롤의 id, 두번째는 선택적으로 사용가능한 '찾을 컨트롤을 포함하는 ASP.NET AJAX 컨트롤 또는 부모 Element'입니다.

$find(id, parent);

* BehaviorID : 모든 ASP.NET AJAX Control Toolkit의 컨트롤은 BehaviorID를 가집니다. 이는 ExtenderControlBase에 기초하고 있으며, 모든 Ajax Toolkit Control은 이를 상속하고 있습니다. 아무튼, 개발자는 BehaviorID를 지정할수도 그렇지 않을 수 도 있습니다. 지정하지 않을 경우 해당 컨트롤의 ClientID와 동일한 값이 Behavior값으로 자동 지정됩니다. 반대로 BehaviorID를 지정한다면 Client에서 해당 컨트롤의 ID는 BehaviorID로 지정됩니다. 즉 JavaScript에서 해당 컨트롤의 ClientID로 해당 컨트롤을 찾을 수 없게 됩니다. 따라서 BehaviorID를 지정했다면, 해당 컨트롤의 ClientID는 무의미 해집니다.

Tag : ASP.NET
Commented by 고맙습니다. at 2009.10.21 16:30 신고  r x
$find(펑션명(),parent); 로 깔끔하고 간단하게 페어런츠의 펑션을 실행시켰습니다.

name    password    homepage
 hidden


ASP.NET Ajax Accordion Control

AJAX Control Toolkit의 Accordion, AccordionPane 컨트롤에 대한 설명입니다. 이 컨트롤에 대한 자세한 설명(영문)은 http://www.asp.net/AJAX/AjaxControlToolkit/Samples/Accordion/Accordion.aspx에서 확인하실 수 있습니다. 이 정보는 해당 웹사이트의 내용을 참조하여 작성되었습니다.

  1. 코드 구조 : 각 Accordion의 내용을 직접 입력하실 것이라면 <Panes>태그 내부에 <AccordionPane>을 생성해서 작성해주시면 되고, 만약 Data를 Binding하실 것이라면 <HeaderTemplate>, <ContentTemplate>를 작성하시면됩니다.
    <ajaxToolkit:Accordion ID="accordionID" runat="Server">
        <Panes>
            <ajaxToolkit:AccordionPane ID="accodionPane1" runat="server">
                <Header>제목1</Header>
                <Content>내용1</Content>
            </ajaxToolkit:AccordionPane>
            <ajaxToolkit:AccordionPane ID="accodionPane2" runat="server">
                <Header>제목2</Header>
                <Content>내용2</Content>
            </ajaxToolkit:AccordionPane>
            <ajaxToolkit:AccordionPane ID="accodionPane3" runat="server">
                <Header>제목3</Header>
                <Content>내용3</Content>
            </ajaxToolkit:AccordionPane>
        </Panes>
        <HeaderTemplate>DataBinding으로 Accordion을 사용할 때 구성해야할 제목부분</HeaderTemplate>
        <ContentTemplate>DataBinding으로 Accordion을 사용할 때 구성해야할 내용부분</ContentTemplate>
    </ajaxToolkit:Accordion>
  2. Property 설명
    • SelectedIndex – 시작시 기본적으로 펼쳐보일 패널의 Index번호
    • HeaderCssClass – Header 부분에 적용될 CSS
    • HeaderSelectedCssClass – 선택된 Header에 적용될 CSS
    • ContentCssClass – 내용에 적용될 CSS
    • FadeTransitions – Accordion의 내용이 전환될 때, Fade의 적용여부. IE6에서 테이블내부에 위치한 Accordion에 이 속성을 True로 설정하면 AccordionPane 사이의 공간에 영향을 미칠 수 있습니다. 또한 고해상도를 사용하는 시스템의 IE6에서 속도 저하 현상이 발견될 수 있습니다.
    • TransitionDuration – 전환 시간(millisecond)
    • FramesPerSecond – 전환 애니매이션의 초당 프레임수
    • AutoSize – Accordion 컨트롤의 크기
      • None – 제한없이 Accordion 컨트롤의 크기가 확장되거나 축소됩니다. 같은 페이지의 다른 컨트롤의 위치에 영향을 미칠 수 있습니다. 기본값으로 사용됩니다.
      • Limit – Height 속성에 지정된 높이보다 커지지 않습니다. 이 높이보다 큰 내용이 위치한다면 스크롤이 생깁니다.
      • Fill – Height 속성의 높이로 항상 고정합니다.
        * IE6과 7에서는 CSS에서 Max-height 속성을 지원하지 않기 때문에 Limit와 Fill은 동일하게 나타납니다.
    • RequireOpenedPane – 모든 패널이 닫히지 않고, 반드시 하나의 패널은 열려있도록 합니다.
    • SuppressHeaderPostbacks – True로 설정하면 Header내부에 위치한 모든 링크가 작동하는 것을 막습니다.
    • Panes - AccordionPane의 컬렉션입니다.
    • HeaderTemplate – Databinding로 Accordio Control을 사용할 때, Header의 내용을 위치하는 곳입니다.
    • ContentTemplate - Databinding로 Accordio Control을 사용할 때, Header의 내용을 위치하는 곳입니다.
    • DataSource - DataSource입니다.
    • DataSourceID - DataSourceControl의 ID를 지정합니다. DataSource Property와 동시에 사용될 수 없습니다..
    • DataMember - DataSourceID를 사용할 때 DataMember를 지정합니다. DataSourceID에 있는 List나 Table명이 지정됩니다.
Tag : ajax, ASP.NET

name    password    homepage
 hidden


ASP.NET Ajax ModalPopup UpdateProgress

ASP.NET Ajax를 사용하다보면 자연스럽게 사용하게 되는 컨트롤이 바로 UpdateProgress입니다. 하지만 이 UpdateProgress를 화면의 가운데 띄운다거나, 처리 중에 다른 버튼을 클릭함으로서 발생하는 다양한 문제들을 피하기 위해 Modal Window를 띄우길 원한다면, UpdateProgress만으로는 처리가 힘듭니다. CSS만으로 분명 화면의 가운데  UpdateProgress를 나타낼 수 있지만, IE6만은 CSS의 갖은 편법을 이용해야하고, 사용한 편법때문에 뒤이어 터지는 문제로 골머리 앓는 경우도 있습니다.

다음은 Ajax Control Toolkit에서 제공하는 Modal Popup Extender를 이용하여 작성한 ModalPopup UpdateProgress입니다.

이 기능을 구현하는데는 UpdateProgress를 이용하지 않습니다. <div runat="server' />엘리먼트가 UpdateProgress를 대신합니다. 먼저 다음과 같이 UpdateProgress로 사용할 메시지를 작성합니다.

<div id="div_updateProgress" class="updateProgress
        style="display:none;" runat="server">
    <p
         작업이 진행 중입니다... 
         <input type="button" value="stop" onclick="AbortPostBack()" />
    </p>
</div>
<cc1:ModalPopupExtender ID="modalPopupUpdateProgress"
        runat="server" TargetControlID="span_fake"
        BackgroundCssClass="modalPopupBack
        PopupControlID="div_updateProgress" />
<span id="span_fake" style="display: none;" />

위의 코드는 취소버튼을 포함하고 있는, Ajax Modal Popup입니다. 다음에는 ASP.NET에서 제공하는 Javascript 객체를 이용하여 이 팝업이 적절한 순간에 나타났다가 사라지게 만듭니다. 다음 자바스클비트 코드를 <body> 하단에 넣어 줍니다.

beginReq라는 함수에 딜레이 시간을 설정할 수 있습니다. 이 시간을 0으로 한다면, 요청이 시작되지마자 ModalPopup UpdateProgress가 나타나게 됩니다. 그 외 다른 설명은 하지 않겠습니다. 별로 어려울것 없고, 제가 주석까지 친절하게 달아두었기 때문에.......

<script type="text/javascript" language="javascript">
    var ModalProgress = '<%= modalPopupUpdateProgress.ClientID %>';
    //AJAX Modal UpdateProgress And Abort Button
    var prm;
    window.onload = function()
    {
        //Abort Button
        prm = Sys.WebForms.PageRequestManager.getInstance();
       prm.add_initializeRequest(InitializeRequest);

       //Modal UpdateProgress Popup
        prm.add_beginRequest(beginReq);
        prm.add_endRequest(endReq);
    }
    //enable abort function
    function InitializeRequest(sender, args)
    {
        if (prm.get_isInAsyncPostBack())
            args.set_cancel(true);
    }
    //Abort asynchronous postback request
    function AbortPostBack()
    {
        if (prm.get_isInAsyncPostBack())
            prm.abortPostBack();
    }
    //set delay time and show the popup after delay
    function beginReq(sender, args)
    {
        setTimeout('showUpdateProgressPopup()', 300);
    }
    //hide the popup when the request is done
    function endReq(sender, args)
    {
        $find(ModalProgress).hide();
    }
    //show the popup if the request is not finished yet
    function showUpdateProgressPopup()
    {
        if(prm.get_isInAsyncPostBack())
            $find(ModalProgress).show();
    }
</script>

다음은  Modal Popup와 팝업이 나타났을 때, 전체페이지에 적용되는 CSS를 작성합니다.

.AjaxModalPopupBackground
{
    background-color:Gray;
    filter:alpha(opacity=70);
    opacity:0.7;
}
.updateProgress 
{
    width: 200px;
    height: 50px
    background-color: White;
    border: 1px black solid;
    text-align: center;  
}
.updateProgress p { margin: 5px;}

위와 같은 코드를 모두 작성하면, Ajax요청이 있을 때마다 작성한 Popup이 나타나게 되며, 요청이 끝나면 자연스레 사라집니다. 또한 요청 취소버튼까지 제공되므로 보다 유연한 웹 어플리케이션이 될 것입니다!!

마지막으로, 대충 소스만 올린점 죄송스럽게 생각하며, 스샷하나도 없다면 머리 아파하실 것 같아 아래와 같은 스샷 첨부합니다.

Tag : ModalPopupExtender, UpdateProgress

name    password    homepage
 hidden


ASP.NET Ajax Extensions

ASP.NET Ajax는 Ajax 프로그램의 구현을 쉽고 간단하게 해줍니다. .NET3.5에 포함된 기본 Ajax Extensions는 ScriptManger, UpdatePanel, UpdateProgress, Timer, ScriptMangerProxy를 제공하고 있습니다.

한가지 참고할 점은 Ajax의 큰 장점 중 하나가 네트워크 트래픽을 크게 감소시킬 수 있다는 점인데, ASP.NET Ajax에서는 그 효과를 크게 볼 수 없다는 것입니다.(이 부분을 고려하여 체계적으로 개발한다면 통신 트래픽을 감소시킬 수는 있습니다만) 다만 ASP.NET Ajax를 사용하여 사용자에게 보다 편리하고 흐름이 끊기지 않는 User Interface를 적은 개발 비용으로 제공할 수 있다는 점은 큰 강점입니다.

ScriptManager

ASP.NET 페이지에서 ASP.NET Ajax기능을 사용하기 위해서는 반드시 ScriptManger을 추가하여야 합니다. 통상적으로 Form 태그 바로 아래 위치하며, 반드시 From태그 안에, 다른 Ajax 컨트롤 위에 있어야 합니다.(아시겠지만, ASP.NET페이지의 컨트롤은 순차적으로 해석되기 때문에 컨트롤들의 순서에 따라 결과가 달라지곤 합니다.)

ScriptManager의 기본적인 역할은 ASP.NET Ajax컨트롤들이 작동하는데 필수적인 스크립트 라이브러리를 페이지에 포함시키는 것입니다.

  • EnablePartialRendering : 기본 값은 True로서, Ajax컨트롤들이 비동기 통신으로 업데이트 될지 여부를 결정합니다. False로 설정하면, 동기방식을 사용하여 업데이트합니다.
  • Script : Script Collection은 지정한 Client Scripts를 페이지에 포함시킵니다.
  • Services : ASMX나 WCF 웹 서비스를 Client Script에서 호출하기 위해서는, 이 곳에 해당 Service가 등록되어야합니다.

UpdatePanel

UpdatePanel은 Panel컨트롤과 같이 다른 컨트롤들을 그룹화 해주는 컨트롤입니다. 하지만 Panel Control과의 차이점이라면 Ajax를 이용하여 비동기적으로 패널 내부를 업데이트 시켜준다는 점입니다. 이 UpdatePanel의 주요 속성은 다음과 같습니다.

  • UpdateMode
    • Always : 모든 PostBack요청에 대해서 UpdatePanel이 Update됨을 보장한다는 의미입니다. 심지어 다른 UpdatePanel에 포함된 컨트롤의 PostBack요청에 대해서도, 전체 Full PostBack에 대해서도 해당 UpdatePanel은 Update됩니다.
    • Conditional : 항상 UpdatePanel을 업데이트 시키는 것이 아니라, 특정 조건에서만 업데이트 시킵니다. 해당 UpdatePanel에서 허용한 컨트롤에 의해서만 업데이트가 일어나게 되는 것입니다. Conditional일 때, UpdatePanel이 Update되는 경우는 다음 세가지 경우입니다.
      1. ChildrenAsTriggers이 True로 되어 있고, 자신에 포함된 컨트롤이 PostBack를 요청한 경우.
      2. 해당 UpdatePanel의 Triggers Collection에 등록된 컨트롤이 PostBack요청을 발생시킨 경우.
      3. 아래와 같이 코드 비하인드(*.cs)에서 명시적으로 Update() 메서드를 호출한 경우.
        UpdatePanel1.Update();
  • ChildrenAsTriggers : True로 할경우 UpdatePanel에 포함된 모든 컨트롤의 PostBack요청을 비동기적으로 처리합니다. False로 할 경우, Triggers Collection에 등록된 컨트롤만 PostBack 요청을 처리하게 됩니다. 이 모드가 True가 되기위해서는 UpdateMode가 Always이여야 합니다.
  • Triggers : UpdatePanel을 업데이트 시키는 Trigger(방아쇠)를 등록합니다. Trigger의 종류는 두가지가 있는데 AsyncPostBack과 PostBack입니다.
    • AsyncPostBack : 비동기적인 PostBack시킬 컨트롤을 등록합니다. 여기서 등록된 컨트롤들은(심지어 UpdatePanel 외부에 위치하더라도) UpdatePanel 을 비동기적으로 Update시킵니다.
    • PostBack : 동기적인 Update를 발생시킵니다. 여기에 등록된 컨트롤은(심지어 UpdatePanel 내부에 위치하더라도) 동기적인 PostBack를 일으킵니다. 이 PostBack Trigger가 대표적으로 사용되는 경우는 파일 Upload입니다. 파일은 비동기 방식으로 Upload될 수 없습니다.
  • RenderMode : Panel을 Client로 Rendering할 때, 어떤 태그로 렌더링 할지 결정합니다.
    • Block : Panel은 Block요소인 Div태그로 표현됩니다.
    • Inline : Panel은 Inline요소인 Span태그로 표현됩니다.
  • EnableViewState : Ajax의 중요 장점 중 하나는 HTTP 전송 데이터가 적어 네트워크 부하가 적게 걸린다는 것입니다. 하지만 .NET의 Ajax는 ViewState는 물론이고 일반 PostBack과 맞먹는 많은 데이터를 비동기적으로 전송합니다. 이 중에 ViewState가 차지하는 데이터는 실제로 어마한데, 이 ViewState를 사용하지 않는다면 False로 하여 데이터 전송량을 줄 일 수 있습니다. ViewState는 사용자가 사용할 수 있지만 각 컨트롤들도 컨트롤의 상태정보를 저장하기 위해서 사용합니다. 예를들어 CommandArgument나 CommandName 등이 ViewState를 이용하는 대표적인 데이터입니다. ViewState가 false가 되더라도 크게 문제될 것은 없으므로 특별한 문제를 일으키지 않는한 False로 하는 것이 성능 향상에 도움이 됩니다.

UpdateProgress

UpdateProgress는 UpdatePanel이 비동기 요청을 처리할 때, 나타날 Panel입니다. 특정 UpdatePanel을 지정하는 것만으로도 해당 UpdatePanel이 요청을 처리 할때, 이 UpdateProgress가 화면에 나타나게 됩니다.

  • DisplayAfter : 1/1000초의 값이 지정됩니다. UpdatePanel이 비동기 요청을 전송한 후 몇 초 뒤에 UpdateProgress가 나타날지 결정합니다. 500을 지정하면 UpdatePanel이 요청을 처리한지 0.5초 뒤에 UpdateProgress가 나타나게됩니다.
  • AssociatedUpdatePanelID : 대상 UpdatePanel을 지정합니다. 지정된 UpdatePanel이 처리 중일 때, 이 UpdateProgress가 화면에 출력되게 됩니다.
  • DynamicLayout : False로 한 경우, UpdatePanel은 보이던 보이지 않던, 그 공간을 차지하게 됩니다. True로 할 경우, UpdateProgress가 출력될 때에만 공간을 차지하게 됩니다.

다음은 UpdateProgress에서 비동기 요청 취소 버튼을 사용하는 예입니다.

<script type="text/javascript">
//Ajax .NET 취소 버튼 함수
window.onload = function()
{
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_initializeRequest(InitializeRequest);
    function InitializeRequest(sender, args)
    {
      if (prm.get_isInAsyncPostBack())
          args.set_cancel(true);
    }
    function AbortPostBack()
    {
      if (prm.get_isInAsyncPostBack())
           prm.abortPostBack();
    }
}
</script>

<asp:UpdatePanel ID="up1" runat="server">
    <ContentTemplate>
        <asp:Button ID="bt1" runat="server" Text="OK" onclick="bt1_Click" />
        <asp:TextBox ID="TextBox1" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel>

<asp:UpdateProgress ID="progress1" runat="server" DisplayAfter="150">
    <ProgressTemplate>
        <div ID="div_updateProgress">
            작업이 진행 중입니다...
            <input type="button" value="stop" onclick="AbortPostBack()" />
        </div>
    </ProgressTemplate>
</asp:UpdateProgress>

Timer

일정 간격으로 PostBack을 발생시킵니다. 자체 이벤트 메서드를 가질 수 있으며, UpdatePanel에 포함되어있든 그렇지 않든 상관없이 페이지를 지정된 시간간격으로 PostBack시킵니다.

ScriptMangerProxy

ScriptManager은 하나의 페이지당 하나만 존재할 수 밖에 없습니다. 하지만 Master Page에서 ScriptManger를 사용하고, 하위 자식 MasterPage나 Page들에서 ScriptManager가 사용될 필요가 있을 경우에 이 ScriptManagerProxy가 사용될 수 있습니다. 보통 ScriptManager은 최상위 MasterPaer의 것이 자식까지 모두까지 적용되기 때문에, 보통의 경우에는 자식 Page에 따로 ScriptManagerProxy가 등록 될 필요는 없습니다.

Tag : asp.net ajax

name    password    homepage
 hidden


ASP.NET 3.5 GridView에서 Ajax Pop-up을 이용한 상세정보 표시

이 정보는 Visual Studio 2008(.NET Framework 3.5)에서 실행한 예제입니다. 또한 GridView의 기본과 <%# Eval() %>를 이용한 바인딩, ASP.NET의 기본적인 동작을 아시는 분들을 목적으로 제작된 글입니다.
image

GridView의 특정 행에 대한 상세정보를 팝업으로 표시하기 위해서 ASP.NET Ajax Control Toolkit의 PopupControlExtender를 이용할 것입니다.

먼저 ASP.NET Ajax Control Toolkit를 사용하기 위해선 ASP.NET Ajax Control Toolkit의 설치가 필요합니다. (여기에서는 .NET Framework 3.5 SP1에서 AjaxControlToolkit-Framework3.5SP1을 설치하였습니다.

  1. .NET Framework 3.5 SP1을 설치합니다. 파일을 다운로드 하신 후에 실행하시면 됩니다. 모든 프로그램이 실행되지 않은 상태에서 설치하실 것을 권하며, 설치 중 다른 프로그램으로 인해 설치를 진행할 수 없다고 한다면 일단 '무시'를 통해 설치를 강행해보시길 바랍니다.
  2. AjaxControlToolkit-Framework3.5SP1을 다운로드 하여 압축을 풉니다.
    image 
  3. Solution Explorer에서 마우스 오른쪽 버튼을 클릭 후, Add Existing Item...을 선택합니다.
    clip_image002
  4. Open 창이 나타나면 AjaxControlToolkit-Framework3.5SP1.zip의 압축을 푼 폴더에 가서 AjaxControlToolkit-Framework3.5SP1\SampleWebSite\Bin\AjaxControlToolkit.dll 파일을 선택하여 dll파일을 프로젝트에 추가합니다.
    image
  5. 새로운 웹 사이트를 생성하신 다음에, Toolbox에 새 탭을 추가합니다.
    image
  6. 추가된 새탭에 마우스 오른쪽 버튼을 누르신후 'Choose Items...'를 선택하여, Choose Toolbox Items 창이 나타나면 'Browse...' 버튼을 선택합니다.
    image
  7. Open창이 뜨면, 현재 솔루션에 추가된 AjaxControlToolkit.dll파일을 선택한 후, Choose Toolbox Items창에서 확인 버튼을 클립합니다.
  8. 다음과 같이 Ajax Control들이 추가된 것을 확인하실 수 있습니다.
    image

이제 Ajax 컨트롤들을 사용하실 준비가 끝이 났습니다. 이제 GridView를 추가하고 Popup창을 띄어보겠습니다.

먼저 화면에 GridView를 하나 그리고, DataSource를 원하는 것으로 연결하여 그리드 뷰로 데이터들이 출력되게 합니다.
image

먼저 페이지의 상단에 Ajax Control Toolkit의 ToolkitScriptManager과 Panel 컨트롤을 하나씩 추가합니다. ToolkitScriptManager은 Ajax Control Toolkit를 사용하기 위해 필요한 컨트롤이며, Panel컨트롤은 추후에 팝업될 컨트롤입니다.

이제 GridView에 TemplateField를 추가합니다. 다음과 같이 템플릿 편집 모드로 와서 ItemTemplage의 공간에 Image를 하나 추가하시고, SmartTag에서 Add Extender를 클릭합니다.
 image

나타나는 Extender Wizard창에서 Popup Control Toolkit를 선택합니다.

 image

다시 Image의 SmartTag에서 Add Dynamic Populate page method를 선택하면 자동으로 해당 메서드가 .cs파일에 추가가 됩니다. 이 메서드는 string를 반환하는데, 이 반환 값에 Popup창에 나타날 HTML을 작성할 것입니다.

image 

추가된 메서드
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string GetDynamicContent2(string contextKey)
{
    return default(string);
}

메서드를 작성하기 전에 다시 디자인 페이지로 돌아와서, 페이지 소스에서 cc1:PopupControlExtender태그를 찾아 다음과 같이 수정을 합니다.

<cc1:PopupControlExtender
                  ID="Image1_PopupControlExtender"
                  runat="server"
                  DynamicServiceMethod="GetDynamicContent2"
                  DynamicServicePath=""
                  DynamicContextKey='<%# Eval("CategoryID") %>'
                  DynamicControlID="Panel1"
                  PopupControlID="Panel1"
                  Enabled="True"
                  ExtenderControlID=""
                  TargetControlID="Image1">
</cc1:PopupControlExtender>

PopupControlExtender의 각 속성들의 의미는 다음과 같습니다.

  • DynamicServiceMethod : 팝업창이 나타나야 할 때, 서버측에서 실행될 메서드의 이름을 지정합니다. 이 속성의 값은 위에서 Add Dynamic Populate page method를 클릭했을 때 자동으로 추가된 것입니다.
  • DynamicControlID : 함수의 리턴값을 받아 출력될 개체의 ID를 지정합니다.
  • PopupControlID : 팝업될 컨트롤의 ID입니다.
  • DynamicContextKey : DynamicServiceMethod에 지정된 함수로 전달될 매개변수를 지정합니다.
  • TargetControlID : 팝업 창이 나타나게 하는 컨트롤을 지정합니다.
  • Position : TargetcontrolID의 어느 부분에 팝업이 나타날지 결정합니다.
  • DynamicServicePath : DynamicServiceMethod로 지정한 메서드가 다른 페이지에 존재할 경우, 이 속성 값으로 해당 페이지를 지정해 줍니다.

이제 DynamicServiceMethod에 지정한 함수를 구현합니다. 매개변수를 받아서, 적절한 데이터를 조회하고 그에 따른 HTML을 StringBuilder를 통해 작성합니다.
(String들을 '+'연산자로 합치는 것은 상당한 리소스를 사용하게 됩니다. 따라서 StringBuilder를 통해서 문자열을 결합 시킬 수 있는데, String와 비교했을 때 리소스 소모의 차이가 어마어마하기 때문에 StringBuilder을 사용하실 것을 권장합니다.)

참고할 만한 추가적인 작업

GridView에 의해서 여러 행들이 생성되면 각 PoputControlExtender과 Image들은 모두 같은 ID와 속성 값을 가지게 됩니다. 만약, 각 행마다 컨트롤들의 ID나 속성값을 다르게 하기 위해서는 다음과 같은 추가적인 작업이 필요합니다.

먼저 Grdiview의 RowCreated이벤트를 구현해야 합니다. 그리드 뷰를 선택하고 속성창에서 Events버튼(번개 아이콘)을 클릭합니다.
image 

RowCreated를 선택하여 해당 이벤트를 생성합니다. 각 행마다 생성되는 PoputControlExtender와 Image의 ID와 BehaviorID의 중복을 없에기 위해서는 다음과 같은 작업이 필요합니다. 아래 소스는 위에서 구현한 Popup이 MouseOver, MouseOut 이벤트에 따라 나타나거나 사라지는 기능을 부여합니다.

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
     //현재 행에서 컨트롤을 찾습니다. 
      AjaxControlToolkit.PopupControlExtender pce = 
                                             e.Row.FindControl("PopupControlExtender1")  
                                             as AjaxControlToolkit.PopupControlExtender;
      Image image = (Image)e.Row.Cells[1].FindControl("Image1");

      // BehaviorID를 지정합니다. 이 값은 클라이언트에서 각각의
      //PoputControlExtender의 동작을 구분하기 위한 값입니다.
      string behaviorID = string.Concat("pce", e.Row.RowIndex);
      if(pce != null)
            pce.BehaviorID = behaviorID; 

      //Image에 적절한 이벤트를 넣어줍니다. $find()는 Jquery로 구현된 Ajax구문입니다.
      // hidePopup()과 showPopup()의 호출을 통해서 사용자가 팝업을 제어할 수 있습니다.
      string strOnMouseOver = string.Format("$find('{0}').showPopup();", behaviorID);
      string strOnMouseOut = string.Format("$find('{0}').hidePopup();", behaviorID);  
      if(image != null)
      {
            image.Attributes.Add("onmouseover", strOnMouseOver); 
            image.Attributes.Add("onmouseout", strOnMouseOut);
      }
   }
}

Tag : ajax, ASP.NET
Commented by Favicon of http://www.mobilepro.pe.kr BlogIcon 몽중인 at 2009.01.14 21:22 신고  r x
좋은 정보 감사합니다.
퍼가면.. 문제가 될까요??....
Replied by Favicon of http://thankee.tistory.com BlogIcon thankee at 2009.01.23 13:33 신고 x
상관없습니다. 다만 출처는 표시해야겠지요..^^

name    password    homepage
 hidden


ASP.NET 3.5

Tim Berners-Lee에 의해서 HTTP를 통한 전송이 성공하고 나서 웹은 급격하게 성장을 이루었습니다. 시스템에 상관없이 데이터를 전송하고 표현하기 위한 시도들이 이루어졌고, 그 결과 HTML과 XML이 태어나게 됩니다. 이 후로도 급격한 성장을 이루어 웹을 통해 모든 데이터가 소통되고 수많은 웹어플리케이션이 개발되면서 기업들은 환경에 구애 받지 않는 통합된 웹 개발 환경을 가지고 쉽게 설계하고, 개발하고, 서비스할 수 있는 것을 원하기 시작했습니다.

이런 결과로서 많은 소프트웨어 벤더들인 이러한 시도에 참여하게 되었고, ASP.NET도 그 결과물 중에 하나입니다. .NET로 통합된 환경은 3.5버전까지 출시되기에 이르렀고 통합된 막강한 개발환경으로 효율적이고 생산적인 개발을 지원하는 대표적인 IDE/언어/Framework로 자리매김하고있습니다.

초창기 웹

처음 HTML만으로 이루어진 정적인 페이지를 서비스하다가 동적인 서비스를 할 수 있는 기술이 소개되었습니다.

  • 서버에서 실행되는 프로그램, CGI : 서버에서 실행되어 사용자의 요구에 맞추어 동적인 페이지를 반환할 수 있도록 하는 프로그램입니다. 혁신적인 기술 이었지만 한번의 요청마다 하나의 프로세스를 생성하는 비효율적인 자원 소비로 인해 현재는 거의 사용되지 않는 기술입니다.
  • 서버에서 실행되는 Script, PHP, ASP, JSP : 스크립트와 컴파일언어의 차이점을 말한다면, 아마도 해석되는 시점과 소스코드의 위치의 차이가 될것입니다. 컴파일 되지 않는 상태로 HTML과 함께 한페이지에 존재하다가, 페이지가 요청되면 한줄한줄 씩 해석되어 실행됩니다. 이러한 언어는 급격하게 퍼지고 많은 사랑을 받고, 현재까지도 애용되고 있는 방식이긴 하지만 코드의 혼잡성, 하드코딩으로 인한 개발 효율 저하, 비효율적인 개발/디버깅 환경, 통합되지 않는 개발환경을 가진다는 단점을 안고있습니다. 물론 일부분은 해결되고 있지만 여전히 개발에 있어 효율성은 떨어집니다. CGI보다 훨씬 효율적으로 자원을 소모하지만, 현재 ASP.NET나 JSP와 같은 컴파일되어 서비스 되는 언어보다 속도에서 많이 떨어진다는 단점이 있습니다.
  • 그리고 ASP.NET : 통합된 개발환경, 효과적인 디버깅 환경, 월등한 생산성, 컴파일 언어의 속도까지, 현재까지 웹 어플리케이션 개발에서 안고 있었단 대부분의 단점을 해결된 통합 개발 환경이 ASP.NET입니다. 기존의 발전된 Windows Applition개발환경과 언어의 장점까지 모두 흡수하여 개발자와 기업에게 개발에 있어 많은 이익을 가져다 주는 언어로서 현재 시점에서 많은 기업들에 의해 채용되고 또한 급격하게 확산되어가는 추세이 있습니다.

ASP가 공개되었을때, 수많은 개발자에게 있어서는 완벽한 언어였습니다. 기존에 자신이 알고있던 개발 언어의 문법으로 추가적인 웹에 대한 이해만 있다면 웹 개발을 할 수 있었기 때문입니다. 그리고 각종 확장 기능을 ASP에서 사용할 수 있었기 때문에, 확장성 까지 갖춘 최고의 언어였습니다.

하지만 곧 많은 단점들이 드러나기 시작합니다. 일단 모든 변수가 variant타입으로서 많은 메모리의 차지는 물론 속도의 저하까지 가져왔으며, 변수의 타입은 실제로 동작하기 이전까지 개발자가 추측은 할 수 있었지만 정확하게 알 수 없었습니다. 물론 수많은 ASP개발 환경이 Text-Editor일 수 밖에 없었던 이유는 역시 뛰어난 확장성과 알수 없는 변수 타입으로 실제 해석되기 전까지 정확한 변수 사용인지, 정확한 컴포넌트 사용인지 개발 툴에서 검사하기 힘들다는 점입니다.

이러한 단점을 개선하고자 ASP.NET는 ASP로부터 많은 것을 버리고 새로운 것을 받아 들였습니다. 비록, ASP.NET는 개발자에게 새로운 환경, 문법, 기술 등을 익히도록 강요하였지만, 그를 만회하고도 남는 엄청난 개발 효율성으로 많은 사랑을 받고 있습니다. 기존의 스크립트 방식에서 컴파일 방식으로 변화되어 속도에서또한 월등합니다.

.NET Framework를 기반으로하는 ASP.NET

.NET Framework는 수많은 클래스 라이브러리를 지원합니다. 체계적으로 namespace에 의해 체계하된 클래스 라이브러리를 언제든지 사용할 수 있습니다.

Interprete가 아닌 Compile되는 ASP.NET

Interprete 언어가 Compile언어보다 느리다는 점은 이미 널리 알려진 사실입니다. 모든 .NET 언어와 마찬가지로 ASP.NET도 컴파일되어 작동합니다. 모든 .NET언어는 먼저 언어중립적 코드인 중간언어로 바뀝니다.(IL : Intermediate Language) 이 IL은 어셈블리 파일로서 페이지가 호출되고 실행되기 직전에 JIT(Just-in-Time) Compiler에 의해 저레벨 기계어 코드로 바뀝니다. 어셈블리 파일인 IL은 .NET Framework가 실행되는 모든 환경으로 배포되어 사용될 수 있습니다.

하지만 매번 사용자의 실행 요청마다 IL로 변환하고, 또다시 기계어 코드로 변환하는 것은 좋지 않은 현상입니다. 다행스럽게도, 첫번째 수행 요청이 있을 때, IL로 해석되고, 기계어 코드 역시 Framework의 Temporary폴더에 저장되고, 또한 캐시되어 실행 속도를 향상시킵니다.

어셈블리 파일의 Disassemble

IL 코드를 확인하기 위해서는 IL Disassembler를 실행하여 DLL이나 EXE파일을 선택하시면 됩니다. 시작->VisualStudio 폴더-> Visual Studio 200X Command Prompt를 실행하여, ildasm.exe를 실행하시면 Disassembler가 실행됩니다. Visual Basic와 C#으로 동일한 기능을 하는 간단한 프로그램을 역어셈블하면 어셈블리 코드가 거의 같다는 것을 알 수 있습니다. .NET에서 다른 언어로 같은 기능을 하는 프로그램을 만들면, 약간의 차이가 있을 확률은 있겠지만, CLR이 따르는 CLS에 의해 거의 같은 성능을 낼 수 밖에 없습니다.

CLS(Common Language Specification)

CLR(공용 언어 런타임)은 모든 객체들과 상호작용하기 위해 특정한 룰을 제공합니다. 이 룰의 집합이 CLS입니다. CLS는 모든 언어들이 반드시 따라야하는 규칙을 말합니다. CLR환경에서 작동하는 IL코드를 생성하는 컴파일들은 CLS에 따른 룰을 따릅니다.

Common Language Runtime과 ASP.NET

ASP.NET는 .NET Framework라는 CLR환경에서 동작합니다. .NET Framework환경에서 동작함으로서 얻을 수 있는 이익은 다음과 같습니다.

  • Garbage Collection : .NET Framework는 .NET 프로그램들의 메모리 할당과 해제를 관리합니다. 예전의 C/C++과 같이 메모리 할당과 해제에 관해서 힘들어 하실 필요없습니다. 참조가 되지 않는 모든 영역은 해제되며, 모든 메모리 공간 요청은 자동적으로 .NET Framework에서 할당되고 관리됩니다.
  • Type Safety : 프로그램이 컴파일될 때, 어셈블리 파일에 사용가능한 클래스, 멤버, 데이터 타입등의 정보를 담습니다. 따라서 다른 어플리케이션이 해당 어셈블리를 호출한다고 하더라도, 적절한 정보를 제공해줄 수 있고 유효성 검사까지 할 수 있습니다.
  • Extensible metadata : 클래스나 메서드에 부여할 수 있는 메타 데이터는 .NET에 의해 어셈블리에 포함이 됩니다. 이러한 메타데이터를 통해 코드를 어떻게 추적하고, 어떻게 컨트롤을 출력할지, 트렌젝션 처리와 풀링은 어떻게 할지 등을 시스템에 알려 줄 수 있습니다.

name    password    homepage
 hidden


ASP.NET 3.0 - LINQ

LINQ는 SQL을 사용하는 데이터베이스 뿐만아니라 XML, DataSet, Object등 다양한 데이터 원본으로 부터 데이터를 입출력 할 수 있도록 해줍니다. 다른 데이터 원본을 연결하더라도 같은 문법을 사용하실 수 있습니다. LINQ는 ASP.NET에서만 사용할 수 있는 것이아니라, 커맨드 라인 프로그램, 윈도 어플리케이션 등 모든 .NET 프로그램에서 사용가능합니다.

LINQ는 향상된 디버깅, 리팩토링, Intellisense의 지원으로 안정적이고 빠른 개발이 가능하게 합니다. 트랜젝션, 뷰, 저장프로시저 외 다양한 새로운 기능들을 지원하며, 비지니스로직과 유효성 검사 코드의 분리를 통해 보다 깔끔하고 체계적인 코드작성이 가능합니다. 성능에 있어서도 동일하거나 더 빠른 속도를 보여주며, LINQ가 제공하는 향상된 기능과 방법들을 사용하면 더욱더 빠른 동작속도를 보장합니다.

LINQ to SQL 시작하기
LINQ to SQL Classes 추가

LINQ to SQL을 시작하기 위해서는 프로젝트에 LINQ to SQL Classes를 추가해야합니다. LINQ to SQL을 추가하면 dbml파일 및 기타 파일들이 시스템에 추가가 됩니다. 그리고 LINQ to SQL에 추가할 데이터베이스를 Server Explorer로 연결이 필요합니다.

LINQ to SQL을 이용한 모델링

LINQ to SQL은 데이터베이스를 쉽게 쉽각화 해주고, 모델링할 수 있도록 하는 LINQ to SQL Designer를 제공합니다.  디자이너 창에 Server Explorer로 나타나는 데이터베이스의 테이블을 끌어다 놓는 것 만으로도 테이블은 클래스화 되며, 각 테이블의 관계에 따라 Designer에 나타나는 클래스들의 관계도 화살표로 표현됩니다. 저장프로시저 또한 Designer페이지에 추가하여 사용할 수 있습니다. Designer페이지에 추가된 테이블 개체들은 Entity Class라고 하며 해당 테이블의 한 행(Row)를 담는 그릇과 같은 역할을 하게 됩니다. Entity Class의 속성들은 실제 DB의 테이블 컬럼과 동일하게 설정됩니다.

Custom Data Context Class

clip_image002[6] clip_image004

LINQ to SQL Designer페이지에 필요한 데이터베이스의 테이블을 끌어다 놓는 등, 모델링 작업이 끝나고 난 다음, SAVE버튼을 클릭하면 모델링한 모든 클래스와 관계, 저장프로시저들이 Custom Data Context Class로서 솔루션에 추가가 됩니다. 추가된 클래스명은 dbml파일명+DataContext이며 ClassView를 통해 추가된 클래스를 확인 하실 수 있습니다. 또한 dbml파일을 열어보면 선언된 클래스들과 이벤트들이 사용자가 쉽게 확장 가능한 partial 클래스와 메서드로 정의되어있습니다. 추가된 Entity 클래스를 통해서 실제 데이터베이스의 데이터를 참조하실 수 있습니다. 하지만 모든 데이터베이스의 테이블들이 Custom Data Context Class로 참조할 수 있는 것이 아니라, Designer페이지에 추가된 테이블들만 Custom Data Context Class을 이용해 참조할 수 있습니다.

Designer 페이지에 추가된 개체들의의 속성을 보시면 Data Source라는 항목이 있습니다. 이 항목의 속성값은 해당 Entity Class에 해당하는 DB상의 테이블 명입니다. 이 항목을 통해 Custom Data Context가 실제 데이터베이스의 테이블을 참조하게 됩니다.

Entity Class

clip_image002[8]

Designer페이지에 모델링된 각 테이블들 역시 각각 클래스화 됩니다. 이것을 Entity Class라고 부르며 테이블의 한 Row값을 담기위한 틀의 역할을 하게됩니다. 즉 Entity Class로 생성된 인스턴스는 테이블의 Row와 같습니다. Custom Data Context Class로 참조하는 DB상의 테이블도 사실은 이 Entity Class의 집합(컬렉션)입니다. Entity Class를 하나 생성한다는 것은 빈 Row를 생성한다는 것이며, 생성된 Entity Class의 인스턴스에 데이터를 할당하여 Data Context Class의 테이블에 추가한다는 것은, 실제 DB에 행을 추가하는 것입니다.

Entity Class의 Property들은 실제 데이터베이스 테이블의 컬럼들이 가지는 모든 특징을 가지게됩니다. 같은 데이터 타입과 제약조건이 각 Property에 적용되며, 따라서 사용자는 Entity Class에 데이터를 입력할 때 데이터 타입과 제약조건에 유의해야합니다.

Naming Classes

Entity Class와 Custom Data Context의 테이블 이름이 약간다르다는 것을 알 수 있습니다. Designer에 테이블들을 모델링할 때, Visual Studio는 DB상의 테이블명을 참조하여 Custom Data Context Class와 Entity Class를 등록하게 되는데, Entity Class는 단수로, Custom Data Context Class에는 복수형으로 이름이 등록됩니다. Region, Products 테이블을 Designer에 등록하면, Entity 클래스는 Region, Product가 되며 Custom Data Context Class에는 Regions, Products로 작명됩니다. Custom Data Context Class에 등록된 이름은 변경이 불가능하지만, Entity Class에 등록된 이름은 Designer 페이지에서 in-line으로 또는 속성창을 통해서 사용자가 수정이가능합니다.

LINQ to SQL에서 실제 DB의 테이블 이름과 Visual Studio에서 사용자에게 제공하는 이름이 다름으로서 발생하는 이익은 다음과 같습니다.

  1. 데이터베이스 종류나 개체들의 이름, 구조를 일부 변경해도 LINQ to SQL 소스코드에 영향을 미치지 않거나, 최소한의 수정만을 요구
  2. 개발에 부적절한 테이블명, 속성 명을 개발에 편한 이름으로 정하여 개발할 수 있음

Relationship Associations

LINQ to SQL에서는 데이터베이스의 기본키/외래키의 관계를 파악하여 자동으로 각 관계들을 처리합니다. Designer에서는 화살표로 부모가 되는 테이블(참조 당하는 테이블)에서 자식 테이블(참조하는 테이블)로 화살표의 방향이 설정되어 표시됩니다. 그리고 부모 테이블의 클래스에는  자신을 참조하는 자식 컬렉션이 추가(자신을 참조하는 자식들을 관리할 수 있음)되며, 자식 테이블의 클래스에는 부모테이블 테이블 클래스의 레퍼런스가 속성으로 추가됩니다.

만약 Designer가 생성한 이름이나 관계들이 마음에 들지 않는다면, 해당 관계의 속성을 통해 이름을 변경하거나 삭제, 수정이 가능합니다.

Delay/Lazy Loading
clip_image002[10]

LINQ to SQL은 각 테이블의 데이터를 사용할 때마다 읽는 것이 아니라, 한번에 미리 읽어서 처리 속도를 향상시킵니다. 하지만 사용자는 특정 컬럼의 데이터가 미리 읽혀질지, 아니면 필요할 때 읽혀질지 결정할 수 있습니다. 만약 이미지 데이터가 저장되는 컬럼이 있는 경우, 이 컬럼은 사용되는 순간 읽혀지도록 하는 것이 더 유리합니다.  따라서 해당 컬럼에 해당하는 속성을 클릭하고 Delay Loaded를 True로 설정함으로서 미리읽기를 끌 수 있습니다.

Stored Procedure
clip_image002[12]

저장프로시저를 LINQ to SQL에 추가함으로서 DataContext 상에서 메서드로서 사용할 수 있습니다. 저장 프로시저를 LINQ에 등록해서 사용하면, 먼저 DataContext를 통해 손쉽게 사용할 수 있다는 점과 엄격한 데이터 타입과 제약조건이 반영되며, 저장프로시저를 통해서 반환된 결과에 변경이 가해져도 LINQ에 의해 추적되고 SubmitChanges()에 의해 DB에 반영됩니다. 물론 LINQ에 정의된 Validation식을 거쳐 변화가 DB에 반영되게됩니다.

저장 프로시저를 Designer에 Drag and Drop할 때, Method Pane에 직접 추가할 경우 반환 데이터 형이 자동으로 결정되는 형태로 생성되며(Variant), 특정 Entity Class 위로 Drag and Drop 할 경우 반환 데이터형은 해당 Entity Class로 결정됩니다. 단, 저장프로시저가 해당 Entity Class의 모든 Property를 반환해야 가능합니다.

보통 LINQ 쿼리문을 이용하여 입력, 수정, 삭제를 할 경우 자동으로 시스템에서 SQL문을 생성하여 실행하게 되는데, 사용자가 지정한 저장 프로시저를 대신에 사용할 수 있습니다. Designer에서 Entity Class를 선택한 뒤, 속성창에서 Delete, Insert, Update의 "..."버튼을 클릭하면 자동으로 생성된 SQL문을 쓸 것인지, 사용자가 지정한 저장 프로시저를 쓸 것인지 결정할 수 있습니다.

SubmitChanges()

LINQ to SQL로 데이터의 일부를 변경하거나 추가했을 때, 그 변경사항은 메모리상에 저장되고 LINQ to SQL에 의해 추적되어 CustomDataContext.SubmitChanges()가 호출 될 때, DB에 반영됩니다. 모든 변경사항은 내부적인 연산을 거처 적절한 SQL문을 생성/실행하여 결과를 DB에 반영시킵니다. 물론 사용자가 데이터를 수정했더라도, 실제 DB의 데이터와 비교했을 때 차이가 없는 경우, 해당 구문은 실행되지 않습니다.

Paging

Skip(), Take() 함수를 사용하여 특정 개수 만큼의 컬럼을 건너뛰거나 특정 개수만큼의 컬럼을 가져 올 수 있습니다. LINQ to SQL은 실제 필요한 부분만을 DB로 부터 전송받기위해  해당 페이징 데이터가 사용될때 DB에 최적화된 SQL코드를 이용하여 데이터를 조회하게 됩니다.

dbNorthwindDataContext db = new dbNorthwindDataContext();
var pro = from p in db.Products
          where p.ProductName.Contains("Toy")
          select p;

db.Products.DeleteAllOnSubmit(pro);
db.SubmitChanges();
showProduct();
//Skip(), Take() 단독으로도 사용할 수 있음

MS Sql 2005을 사용하면  LINQ to SQL은 ROW_NUMBER() SQL 함수를 페이징에 사용하여 성능을 향상시킵니다.

/* MS-SQL Server에서 ROW_NUMBER()을 이용한 간단한 페이징 */
create procedure product_paging
    @startNum int,
    @endNum int
As
    SELECT *
    FROM
        (SELECT ProductName,ROW_NUMBER() OVER (order by ProductID) AS RowNumber
         FROM Products ) AS Product
    WHERE RowNumber BETWEEN @startNum AND @endNum --RowNum을 Between으로 제한
Go

/* 기존의 TOP-N을 이용한 페이징 처리 */
SELECT * --3. 역순으로 반환된 테이블 정렬
FROM (SELECT TOP takeNum * --2. 30~20행을 반환
           FROM (SELECT TOP (takeNum * pageNum) * --1. 3페이지면 1~30행을 반환
                      FROM products
                      ORDER BY 1 ASC) AS product
          ORDER BY 1 DESC) AS descendingProduct
ORDER BY 1 ASC

Enumerable

LINQ to SQL은 IEnumerable 인터페이스를 구현하고 있습니다. 단일 행은 Entity Class로 담게 되지만, 복수 행은 IEnummerable<Table> 컬렉션에 담게됩니다. 그리고 .NET 모든 서버컨트롤은 IEnumerable를 데이터바인딩에 지원하기에 LINQ to SQL의 결과를 서버컨트롤에 쉽게 바인딩 할 수 있습니다.

LINQ to SQL에 구현된 IEnumerable의 주요 멤버함수

- All : 모든 시퀀스가 해당 조건을 만족하는지 반환. All(p => p.UnitsInStock < 100)
- Any : 시퀀스 중 하나라도 조건을 만족하는지 반환. Any(p => p.UnitsInStock == 0)
- Average : 표현식으로 지정된 시퀀스의 평균을 반환
- Count : 시퀀스의 총 개수를 반환.
- Distinct : 시퀀스에서 중복을 제거한 총 개수를 반환
- Concat : 두 시퀀스를 하나로 합칩니다. Concat(NewProduct)
- Except : 두 시퀀스의 차집합을 구합니다. Except(Product2)
- First, Last ; 시퀀스의 첫 번째 혹은 마지막 요소를 반환합니다.
- Where : 사용자가 지정한 조건에 맞는 시퀀스 반환. Where(p => p.ProductId == 1)
- GroupBy : 시퀀스의 요소를 그룹화
- Max, Min : 시퀀스의 지정된 데이터 중 최대값/최소값 반환
- Select : 시퀀스의 요소를 새 폼에 투영. Select(p => p.UnitPrice * p.UnitsInStock)
- OrderBy, OrderByDescending : 시퀀스를 정렬.
- Range : 지정된 범위의 정수 시퀀스 반환. Range(1, 10);
- Reverse : 시퀀스를 반전
- Single : 조건에 맞는 단일 요소 반환. 조건의 결과가 다수일 경우 예외 발생.
- Sum : 시퀀스의 합. Sum(p => p.UnitPrice)
- Skip : 지정한 수 만큼 건너뛴 시퀀스 반환. Skip(10)
- Take : 지정한 수의 시퀀스 반환. Take(10)

LINQ to SQL Query

SELECT : LINQ to SQL을 이용하여 데이터 조회하기

  1. Lambda 식 사용 : 실제 SQL문의 실행 순서대로 입력.(Select문은 항상 마지막)
        dbNorthwindDataContext db = new dbNorthwindDataContext();
        var products = from p in db.Products
                              where p.Category.CategoryName == "Beverages"
                              orderby p.ProductID descending
                              select p;
  2. IEnumerable 멤버함수 사용하기
        dbNorthwindDataContext db = new dbNorthwindDataContext();
        var products = db.Products.Where(p => p.Category.CategoryName == "Beverages");

 

UPDATE : CustomDataContext의 인스턴스를 변경하고, SubmitChanges() 호출

dbNorthwindDataContext db = new dbNorthwindDataContext();
Product product = db.Products.Single(p => p.ProductName == "Toy 1"); 
product.UnitPrice = 99; 
product.UnitsInStock = 5;
db.SubmitChanges();

 

INSERT : EntityClass를 생성하고, 데이터를 입력한 다음 CustomDataContext의 인스턴스에 추가 또는 InsertOnSubmit(), InsertAllOnSubmit()함수를 이용하여 데이터 추가

  1. dbNorthwindDataContext db = new dbNorthwindDataContext(); //DB선언
    Category category = new Category(); //Entity Class 인스턴스 생성
    category.CategoryName = "Scott's Toys"//데이터 입력
    db.Categories.InsertOnSubmit(category); //Insert
    db.SubmitChanges(); //작업 저장

 

DELETE : 삭제할 데이터를 CustomDataContext에서 선택하여, DeleteAllOnSubmit나 DeleteOnSubmit()의 인자로 전달하여 데이터 삭제

dbNorthwindDataContext db = new dbNorthwindDataContext();
var products = db.Products.Where(p => p.Category.CategoryName == "Beverages"); 
db.Products.DeleteAllOnSubmit(products); //매개변수로 전달받은 Entity Classes를 삭제 
db.SubmitChanges();

 

Subset of the result : New 식을 이용하여 결과의 부분 집합을 구할 수 있습니다.

var product = from p in db.Products 
                     where p.Category.CategoryName == "Beverages"
                     select new
                     { 
                         ID = p.ProductID,
                         Name = p.ProductName, 
                         Orders = p.Order_Details.Count, 
                         Revenue = p.Order_Details.Sum(o => o.UnitPrice * o.Quantity) 
                     };

 

Primary Key/Foreign Key : 외래키 관계가 있는 Property에는 원하는 Entity Class의 인스턴스를 할당하면 됩니다. 할당된 Entity Class가 새롭게 만들어진 것이더라도 LINQ to SQL이 자동으로 DB에 반영합니다.

var product = from p in db.Products 
                      where p.Category.CategoryName == "Beverages"
                      select p;
//외래키에 기존의 Category 할당
product.Category = db.Category.Single(c => c.CategoryName == “Seafood”);
//외래키에 새로운 Category 할당
Category category = new Category(); //생성
category.CategoryName = “Software”;
product.Category=category; //할당

사용자 쿼리문 실행

- ExecuteCommand를 이용하여 사용자 DML문 수행 가능
- 영향을 받은 행의 숫자를 반환, 에러 발생시 -1 반환
- DML이 아닌 Select, Create, Drop, Alter 문 등 수행 불가.
db.ExecuteCommand("INSERT INTO products(productName) VALUES('EasyBiz')");

Querying Database

여러 행이 담겨있는 IQueryable<Table> 타입을 검색하는 방법은 다음과 같습니다.

IQueryable<Product> products = db.Products; 
foreach (Product p in products) 
       Response.Write(p.ProductName + "<br>");

Transactions

LINQ to SQL이 SQL문장을 실행 함에 있어서 Transaction을 적용하기 때문에, 모든 변경이 DB에 반영되거나 아니면 모두 반영되지 않습니다. .NET 2.0부터 사용가능한 TransactionScope를 이용, 사용자가 지정한 트랜젝션 범위에 LINQ to SQL이 포함될 수 있습니다. 즉 프로그래머가 지정한 트랜젝션을 사용하여 기존에 데이터 엑세스 코드와 LINQ to SQL간의 트랜젝션을 쉽게 통합할 수 있습니다.

//.NET 2.0에서 제공하는 트랜젝션

using(TransactionScope ts = new TransactionScope())
{
try
{
//각종 데이터 처리 구문
//LINQ 코드 기존의 Transaction에 포함되면, 해당 트렌젝션에 따라 동작합니다.
ts.Complete();
}
catch (DbException ex)
{
conn.Close();
ts.Dispose();
}
}

Validation
clip_image002[14]

개발에 있어서 코드 반복, 통합된 코드 작성은 피해야할 일입니다. LINQ to SQL 역시 유효성 검사 코드와 비지니스 로직을 분리하는 방법을 제공합니다.
  1. Base Validation : 데이터베이스의 테이블이 Designer에 모델링 될 때, 데이터베이스의 각 제약사항과 데이터타입이 모두 LINQ to SQL에 적용됩니다. 따라서 기본적인 데이터 형이나 제약조건(Unique, Nullable, identity 포함)에 대한 검사는 컴파일러에 의해서 자동적으로 이루어집니다. 이 제약조건은 Designer페이지에서 확인할 수 있으며, 사용자가 사용하길 원하지 않는 다면 삭제할 수 도 있습니다.
  2. SQL Injection : 유효성 검사를 하는 중요한 목적은 여러 불안정한 상황에서 벗어나기 위해서입니다. 널리 알려진 SQL Injection을 피하기 위해서 LINQ to SQL은 자동적으로 SQL에 저장될 데이터를 Escape 시킵니다.
  3. Property Validation : 테이블의 각 컬럼값이 변경 될 때마다 발생되는 이벤트를 사용자가 구현할 수 있습니다. 해당 dbml파일에 사용자가 재정의할 수 있는 이벤트들이 정의되어 있습니다. 이 이벤트를 다음과 같이 재정의하여 속성들 각각에 대한 유효성검사 코드를 추가하시면 됩니다. dbml파일안에있는 Partial로 작성된 해당 Entity클래스의 해당 Partial Method를 구현하면됩니다.
    public partial class Customer
    {
       partial void OnPhoneChanging(string value)
        {
            Regex phoeNumber = new Regex(@"0\d{2}-\d{3-4}-\d{4}$");

            if (phoeNumber.IsMatch(value) == false)
            {
                throw new Exception("유효한 연락처(전화/휴대폰)가 아닙니다.");
            }
        }
    }

  4. Entity Object Validation : 각 Entity의 속성 하나하나 검사하는 이벤트를 작성하기 번거롭다면, 다음과 같이 Entity의 유효성 검사 이벤트를 작성하시면 됩니다. dbml파일안에있는 Entity 클래스의 partial void OnValidate()를 구현하면됩니다.
    public partial class Customer
    {
        partial void OnValidate(System.Data.Linq.ChangeAction action)
        {
            Regex phoeNumber = new Regex(@"0\d{2}-\d{3-4}-\d{4}$");
            if (phoeNumber.IsMatch(Phone) == false)
            {
                throw new Exception("유효한 연락처(전화/휴대폰)가 아닙니다.");
            }
            if (phoeNumber.IsMatch(Fax) == false)
            {
                throw new Exception("유효한 팩스번호가 아닙니다.");
            }
        }
    }
  5. Entity Insert/Update/Delete Method Validation : 각 Insert, Update, Delete에 해당하는 이벤트가 Entity에서 발생하면 유효성 검사 코드가 실행되도록 할 수 있습니다. dbml파일에 있는 해당 DataContext클래스의 각 Partial 함수를 구현하면됩니다.

    public partial class NorthwindDataContext
    {
        partial void InsertCustomer(Customer instance)
        {
            this.ExecuteDynamicInsert(instance);
        }
       partial void UpdateCustomer(Customer instance)
        {
            this.ExecuteDynamicUpdate(instance);
        }
        partial void DeleteCustomer(Customer instance)
        {
            this.ExecuteDynamicDelete(instance);
        }
    }

Optimistic concurrency

LINQ to SQL은 동시성 제어를 위해서 Locking를 사용하지 않는 방법인 optimistic concurrency를 제공합니다. 다음과 같은 절차로 충돌을 처리하게 됩니다.

  1. DB서버로부터 값을 얻어 그 값을 클라이언트에 저장하여 그것을 통한 작업을 합니다.
  2. 클라이언트에서 해당 데이터를 통합 작업이 끝난 뒤, DB에 반영하기전에 해당 데이터가 DB에서 변경이 있었는지 검증 작업을 가집니다.
  3. 그 동안에 해당 데이터가 변경되었거나 변경 중에 있다면 충돌을 사용자에게 알립니다.
  4. 충돌 리스트에서 충돌을 확인하고, 충돌을 사용자에게 알려주고 사용자의 선택을 받거나, 작업을 취소하는 등의 처리를 하게됩니다.
  5. 충돌이 없었다면 정상적으로 작업이 커밋됩니다.

<asp:LinqDataSource>
clip_image002[16]

.NET에서 제공하는 여러 DataSource컨트롤과 같이 LINQ에 대해서도 DataSource컨트롤을 제공합니다. 이는 다른 컨트롤에 대한 LINQ의 바인딩을 보다 간단하게 합니다. SqlDataSource 등 다른 DataSource 컨트롤을 사용할 때 보다 얻을 수 있는 장점은, LINQ에서 제공하는 Validation 및 다른 장점들을 활용할 수 있다는 점이 되겠습니다.

실제 SQL쿼리문

clip_image002[18]

실제로 수행되는 SQL쿼리문을 확인하는 방법은 breakpoint를 걸고, 프로그램을 실행하여 디버그 모드로 들어가는 것입니다. 디버그 모드에서 해당 LINQ to SQL 표현식을 보면 실제 수행되는 쿼리문이 나타나는 것을 확인할 수 있습니다.

LINQ to SQL Visualizer

SQL문을 더욱더 효율적으로 확인하고 검사까지 할 수 있는 플러그인이 제공되는데, http://www.scottgu.com/blogposts/linqquery/SqlServerQueryVisualizer.zip에서 다운 받은 다음, 압축을 풀고 \bin\debug\ SqlServerQueryVisualizer.dll 파일을 \Program Files\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\Visualizers\ 폴더에 넣고 비주얼 스튜디오를 재시작 하시면 됩니다. 디버거 모드에서 SQL문 확인 및 평가를 더욱 더 쉽게 할 수 있습니다.


name    password    homepage
 hidden


 Category
분류 전체보기 (95)
Netwrok & Security (6)
Web Development (61)
Database (5)
Framework (6)
Others (17)
About (0)
 TAGS
: ajax Android APM application error #401 ASP ASP.NET asp.net ajax ASP.NET Machine at ATRIX ATX ATX와BTX의차이 Auto-Negotiation back-end bash shell Bit ending Blog API BTX c#.net CentOS class id 차이 CSMACD data tier Database DB DB동작원리 DB처리과정 DTD ebnf ethereal ethernet exception firefox2 설치 font-family Framework과 자동로그인 front-end FTP get post 우선순위 hotmail
 Calendar
«   2018/11   »
        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  
 Visitor Statistics
Total : 269,582
Today : 10
Yesterday : 14
rss