<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>이병무 - Brian Lee &gt; Brian Lee - Town &gt; Study Room | 공부방</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study</link>
<description>테스트 버전 0.2 (2004-04-26)</description>
<language>ko</language>
<item>
<title>Javascript Function to Check or Uncheck all Checkboxes</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=25</link>
<description><![CDATA[
<H1>Javascript-x Function to Check or Uncheck all Checkboxes</H1>
<P class=descript-xion>This Javascript-x function will check or uncheck all the checkboxes in an HTML form.</DIV>
<DIV>This function is specially designed for dynamic pages with varying numbers of checkboxes. Unlike other functions out there, it will work without error even if there are no checkboxes or there is only one checkbox. It is also significantly faster for long lists, because it saves the length of the checkbox in a variable, instead of recalculating it in the loop. Finally, the function is granted to the public domain--use it as you wish. 
<H2>Instructions</H2>
<DIV>Provide the form name and the field name of the checkbox as the parameters to the function. Then specify true or false as the CheckValue, depending on if you want to check or uncheck all the checkboxes, respectively. The function simply returns without doing anything if the checkboxes do not exist, so make sure you enter the correct FormName and FieldName. Remember, unlike HTML, Javascript-x form and field names are case-sensitive! 
<H2>JavaScript-x Source Code</H2><PRE><CODE>
function SetAllCheckBoxes(FormName, FieldName, CheckValue)
{
	if(!document.forms[FormName])
		return;
	var objCheckBoxes = document.forms[FormName].elements[FieldName];
	if(!objCheckBoxes)
		return;
	var countCheckBoxes = objCheckBoxes.length;
	if(!countCheckBoxes)
		objCheckBoxes.checked = CheckValue;
	else
		// set the check value for all check boxes
		for(var i = 0; i &lt; countCheckBoxes; i++)
			objCheckBoxes[i].checked = CheckValue;
}
</CODE></PRE>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Thu, 08 Feb 2007 16:47:04 -0700</dc:date>
</item>
<item>
<title>Permanent Redirect with HTTP 301</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=24</link>
<description><![CDATA[
<H1>Permanent Redirect with HTTP 301</H1>
<P class=descript-xion>This article describes how to properly redirect a web page using an HTTP 301 status code and Location header. The 301 status code is used to indicate that a page has permanently moved. Multiple techniques are presented with recommendations. 
<DIV></DIV>
<DIV>In order to redirect an out-of-print web page to another location, return the HTTP 301 status code and a location header in the HTTP response of the deprecated web page. The HTTP 301 response code will tell user-agents that the location has permanently moved. This is particularly useful for search engines like Google, which will carry over page rank to the new page if this status code is seen. If you do not need to indicate permanent displacement, you can accomplish redirection by setting a Location header in PHP or using Response.Redirect in ASP. The <EM>location</EM> header does the actual redirection to the new location, and can be used by itself.</DIV>
<DIV>HTTP headers are sent for every web page. If you want to see what HTTP headers look like for a particular page, visit <A href="http://www.rexswain.com/httpview.html">Rex Swain's HTTP Viewer</A>. For advanced users, I would recommend you download the <A href="http://www.spreadfirefox.com/community/?q=affiliates&amp;id=3613&amp;t=51">Firefox</A> web browser and install Chris Pederick's <A href="http://www.chrispederick.com/work/firefox/webdeveloper/">Web Developer Extensions</A>. Then, use the <EM>Information-&gt;View Response Headers</EM> function. In script-xs, HTTP headers must be sent before sending any page content, including white space, or else an error will result. 
<H2>HTTP 301 Redirect in ASP-VBScript-x</H2><PRE><CODE>&lt;%@ Language=VBScript-x %&gt;
&lt;%
' Permanent redirection
Response.Status = "301 Moved Permanently"
Response.AddHeader "Location", "http://www.bmlee.com/"
Response.End
%&gt;</CODE></PRE>
<DIV>In Active Server Pages (ASP), <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Response.Redirect</FONT></CODE> does not work the same as the code shown in the example. <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Response.Redirect</FONT></CODE> will set the location header as shown, but it will set the status code to <EM>HTTP/1.1 302 Object moved</EM> instead. When you set the Location header with <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Response.AddHeader</FONT></CODE>, the status code must be manually defined, otherwise it stays <EM>200 OK</EM>. 
<DIV>If you send any page content prior to the headers, you will get an error like, <EM>"Response object error 'ASP 0156 : 80004005'; Header Error; The HTTP headers are already written to the client browser. Any HTTP header modifications must be made before writing page content."</EM>. Normally, you do not see this error even if there is content prior to the redirect, because page buffering is enabled by default in IIS. If you want to be sure there is no content being sent before the redirect, call <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Response.Flush</FONT></CODE> just before it, disable page buffering with <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Response.Buffer = False</FONT></CODE>, or configure IIS to disable page buffering. (Disabling buffering reduces performance.) 
<H2>HTTP 301 Redirect in PHP</H2><PRE><CODE>&lt;?php
// Permanent redirection
header("HTTP/1.1 301 Moved Permanently");
header("Location: <A href='http://www.bmlee.com/");exit();'>http://www.bmlee.com/");
exit();
</A>?&gt;</CODE></PRE>
<DIV>If you set the Location header by itself, PHP automatically sets the status code to <EM>HTTP/1.1 302 Found</EM>. 
<DIV>Note, if you attempt to send headers after content has been sent, you will get a warning like, <EM>"Warning: Cannot modify header information - headers already sent by ..."</EM>. Watch out for empty lines and spaces between PHP open and close tags. ASP ignores these, but PHP does not. 
<H2>HTTP 301 Redirect in ColdFusion</H2><PRE><CODE>&lt;CFHEADER statuscode="301" statustext="Moved Permanently"&gt;
&lt;CFHEADER name="Location" value="http://www.bmlee.com/"&gt;</CODE></PRE>
<DIV>Do not use a <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>CFFLUSH</FONT></CODE> command before the above tags, or in <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>Application.cfm</FONT></CODE>. This Coldfusion code was provided by <A href="http://www.tollfreeforwarding.com/">Toll Free Forwarding.com</A>. 
<H2>HTTP 301 Redirect in Perl</H2><PRE><CODE>#!/usr/bin/perl      -w
use strict;
print "Status: 301 Moved Permanantly\n";
print "Location: http://somewhere/page.htm\n\n";
exit;</CODE></PRE>
<DIV>As in PHP, if you do not supply the 301 code explicitly, Apache will send a "302 Found" status code. Note the subtle difference as compared to PHP. This example prints a "Status" header rather than an HTTP status code line. This is because you <EM>can not</EM> set the HTTP status code directly as you typically can in PHP. If you do, the server will return a 500 Internal Server Error, and the error log will show: <PRE>malformed header from script-x. Bad header=HTTP/1.1 301 Moved Permanently: /cgi/test.pl</PRE>
<DIV>The "Status" header is an alternative way of setting the HTTP status code. This is not passed to the browser directly, but the web server (Apache) converts it into a suitable HTTP status code. (The CGI specification does not allow directly setting the HTTP status code. Perl typically runs as a CGI, whereas PHP does not. For more information, see this <A href="http://www.srcf.ucam.org/faq/cgi#php-header">PHP header FAQ</A> or the <A href="http://us2.php.net/manual/en/function.header.php">PHP header function</A> documentation.) 
<DIV>You must supply the carraige returns as specified above. Two carriage returns (\n\n) are needed after the last header, since they signify the end of the HTTP header and the beginning of content. 
<DIV>As in PHP, it is good practice to exit the script-x explicitly, otherwise, the Perl script-x continues executing. There should not be any <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>print "Content-type: text/html\n\n";</FONT></CODE> or other output before printing these headers, or the headers will be printed as part of the content visible in the browser. 
<H2>Redirection with mod_rewrite</H2>
<DIV>The Apache module, <A href="http://httpd.apache.org/docs/trunk/mod/mod_rewrite.html">mod_rewrite</A>, is typically used to transform URLs from one form to another. It can also be used for permanent redirection. The rewriting rules can be placed in httpd.conf (for server-wide rules), or in .htaccess files (for directory-specific rules). Consider the following example that is in the .htaccess file of this website: <PRE><CODE>rewriteEngine on
rewriteRule ^contact\.php$ <A href="http://www.bmlee.com/p2.php">http://www.bmlee.com/p2.php</A> [R=permanent,L]</CODE></PRE>
<DIV>The first line tells Apache to turn the mod_rewrite engine on. The second line tells mod_rewrite to match requests where the URI is exactly <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>contact.php</FONT></CODE>. The ^ and $ match the beginning and end of the expression, respectively, and the \ is used to escape the period, which otherwise would match any character. After the match pattern is a space, and then the substitution. In this case, I want the server to substitute <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>contact.php</FONT></CODE> with <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe><A href="http://www.bmlee.com/p2.php">http://www.bmlee.com/p2.php</A></FONT></CODE>. 
<DIV>In brackets are the comma-separated rule flags. The <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>R=permanent</FONT></CODE> flag tells Apache to issue a permanent redirect 301 response, with the location as the substituted URL. The <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>L</FONT></CODE> flag tells mod_rewrite that no other subsequent rules should be processed. 
<DIV>Note that I specified the full destination URL in the substitution, because otherwise mod_rewrite uses the short form of my hostname <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>bmlee.com</FONT></CODE>. To avoid Google indexing issues, I've redirected all non-www traffic to the www prefixed host. I also redirect the default, index pages to the root directory. The rules to achieve this are as follows: <PRE><CODE># redirect all non-www traffic
RewriteCond %{HTTP_HOST} ^bmlee\.com$
RewriteRule ^.*$ <A href="http://www.bmlee.com%{REQUEST_URI">http://www.bmlee.com%{REQUEST_URI</A>} [R=permanent,L]

# Redirect aliases of home page to the root website
rewriteRule ^index\.(php|html|htm) <A href="http://www.bmlee.com/">http://www.bmlee.com/</A> [R=permanent,L]</CODE></PRE>
<DIV>I leave it up to the reader to understand this example by reading the mod_rewrite documentation. The mod_rewrite module offers a very powerful and effective way to perform redirection. It is preferable to use mod_rewrite over a server-side script-x. The drawback is the steep learning curve, requiring you to learn both its syntax and the syntax of regular expressions. 
<H2>Redirection with Javascript-x or META tags</H2>
<DIV>If you don't have server-side script-xing or mod_rewrite on your web server, you can still do redirection, but not as elegantly. The Javascript-x/META method will redirect after both the headers and the page have loaded. By contrast, the <EM>HTTP header</EM> method described above redirects immediately after the headers have loaded. While both methods require two requests to the web server, the Javascript-x/META method causes the user's browser to flicker or refresh as the old page is loading. Redirection with HTTP headers is seamless, and saves time. 
<DIV>You can not send a 301 status code via Javascript-x or META tags. Since the HTTP status code of the page will remain <EM>200 OK</EM>, most search engines will continue to think the location is valid. Any page rank of the old location will not be transferred to the new location. 
<DIV>Another disadvantage is that some browsers disable Javascript-x or META refresh. Therefore, one must include a link to the destination page in the body of the page. One can also add a delay between when the page is displayed, and when it redirects. However, I would strongly discourage this and will not even describe it here. 
<DIV>Unfortunately, it is very common to see delayed META/Javascript-x refresh used when a site or page has moved. The page typically shows a message saying, "This site has moved to ... Your browser will be automatically forwarded in X seconds. Click here if your browser does not automatically forward you." Some website, particularly government and legal websites, add such an intermediate page whenever you click a link to an external site. 
<DIV>Not only is this search-engine unfriendly, but it has the additional drawback of wasting the visitor's precious time while they read wholly unneccessary information and wait for the redirect. The first rule of web design (and writing) is to treat your reader's time with respect. All visitors except the most novice can tell when they are leaving your site for another, and that your site has no authority over the external site, so there is no need to waste everyone else's time. 
<H3>Redirection with Javascript-x</H3><PRE><CODE>&lt;html&gt;
&lt;head&gt;
&lt;script-x type="text/javascript-x"&gt;
window.location.href='http://www.bmlee.com/';
&lt;/script-x&gt;
&lt;/head&gt;
&lt;body&gt;
This page has moved to &lt;a href="http://bmlee.com/"&gt;http://bmlee.com/&lt;/a&gt;

&lt;/body&gt;
&lt;/html&gt;
</CODE></PRE>
<DIV>Note that they syntax <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>document.location='';</FONT></CODE> has been deprecated. Use the above code, or alternately, <CODE><FONT style="BACKGROUND-COLOR: #eaeaea" face=GulimChe>document.URL='';</FONT></CODE>. 
<H3>Redirection with META Refresh</H3><PRE><CODE>&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="refresh" content="0;url=http://www.bmlee.com/"&gt;
&lt;/head&gt;
&lt;body&gt;
This page has moved to &lt;a href="http://bmlee.com/"&gt;http://bmlee.com/&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;
</CODE></PRE>
<DIV>As I've pointed out, the META refresh tag should be avoided as a method of redirection. There are other times when it is more useful. A common situation is on a page where information is constantly changing, like news or stock tickers. For example, most major news websites include META refresh tags in their home pages. CNN sets the refresh interval to 1800 seconds, while Google sets it to 900 and Yahoo, to 300. If the user switches to another application for awhile, when they return, they are presented with the most up to date information. 
<DIV>Another situation is in the status page for the execution of a long-running server-side task. A good site design principle is that every web page load within a fraction of a second. For longer tasks, queue and run them on the server, and simply show a status page via the web. The three states of the status page would be <EM>queued</EM>, <EM>running</EM>, and <EM>completed</EM>. The refresh tag would be printed in the <EM>queued</EM> and <EM>running</EM> states, with an appropriate refresh interval like 15 or 30 seconds. You should always put a link to manually refresh the status page, in case the user disabled this META tag in their browser. 
<H2>HTTP/1.1 301 Status Code Definition</H2>
<DIV>
<DIV>From the <A href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP/1.1 Status Code Definitions</A> section of the <A href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</A> RFC 2616, Fielding, et al. See the RFC for all the possible redirection status codes, which include 300-Multiple Choices, 301-Moved Permanently, 302-Found, 303-See Other, 304-Not Modified, 305-Use Proxy, and 307-Temporary Redirect. Using the appropriate status code is worthwhile for public websites, but you can probably leave it unspecified when redirecting in a private or intranet application. 
<BLOCKQUOTE>
<DIV>The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise. 
<DIV>The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). 
<DIV>If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued. 
<DIV>Note: When automatically redirecting a POST request after receiving a 301 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request. </DIV></DIV></DIV></DIV></BLOCKQUOTE></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Thu, 08 Feb 2007 16:38:33 -0700</dc:date>
</item>
<item>
<title>무조건 알아야 할 PHP 속도 테스트 14 가지</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=21</link>
<description><![CDATA[★ 무조건 알아야 할 PHP 속도 테스트 14 가지 ◆◇◆◇◆◇&nbsp; &nbsp; &nbsp; <br/><br/><br/>PHP로 코딩 함에 있어서 알아야 할 속도 테스트 입니다. <br/>조금더 빠른 PHP 속도를 유지 하기 위한 것이죠 ^^ <br/><br/>작은 것이 모여서, 대따 오랜 시간이 걸릴 수 가 있는 것 입니다. !! <br/>되도록이면 속도가 빠른 것을 사용하시는 것이 좋습니다. <br/><br/>물론 함수 마다 기능 마다 장단이 있지만요....^^ <br/><br/><br/>다른 비교가 있으면 알려주셍 ^^ 답변 달아 주세용 ^^ <br/><br/>계속 적으로 업글 됩니다. 현재 14가지 !!!! <br/><br/><br/>========================================================================== <br/>★ mysql 총 게시물 수 세기 <br/><br/>$numresults=mysql_query("select code from $board"); <br/>$numrows=mysql_num_rows($numresults); <br/>2초 이상 ...게시물 10만개 <br/><br/>VS <br/><br/>$numresults=mysql_query("select count(code) as code from $board"); <br/>$row_num=mysql_fetch_array($numresults); <br/>$numrows=$row_num[code]; <br/>0.2&nbsp; ...게시물 10만개 <br/><br/>아래것이 훠얼씬 빠름다.. <br/>도대체 mysql_num_row() 는 왜 만들어 놓은 것일까용??? <br/><br/><br/>========================================================================== <br/>★ mysql_fetch_row&nbsp; &gt; mysql_fetch_array &gt;&gt;&gt; mysql_result <br/><br/><br/>입니다. <br/><br/>row 가 array 보다 약간 빠르고, result 보다는 훠얼씬 빠름당 ^^ <br/><br/>row 는 불편한게 숫자로 칼럼을 불러와서 불편합니다. <br/>array 가 약간 느리지만, 문자 칼럼을 불러 올 수 있으니 array 쓰는 것도 양호 ^^ <br/><br/>아직도 mysql_result() 를 사용하시나요? <br/><br/>========================================================================== <br/>★print , echo ,printf 함수 속도 비교 <br/>HTML 출력 &gt;&gt; echo &gt; print &gt;&gt; printf <br/><br/><br/>print 와 printf 함수는 복잡한곳에 적격이고, 약간 느리다. <br/><br/>echo 는 단순한곳에 적격이고...빠르다. <br/>printf 는 형식화된 출력을 해주므로 그래도 좋죠 ^^ <br/><br/>========================================================================== <br/>★&nbsp; 인라인 <br/><br/>&nbsp;a.php <br/>&lt;? <br/>$aa="sdsdsdsd"; <br/>echo ("&lt;table&gt; <br/>&nbsp;&lt;td&gt; $aa &lt;/td&gt; <br/>&lt;/table&gt;"); <br/>?&gt; <br/><br/>&nbsp;위 랑.. <br/><br/>&nbsp;b.php <br/>&lt;? $aa="sdsdsdsd"; ?&gt; <br/>&lt;table&gt; <br/>&lt;td&gt;&lt;? echo $aa; ?&gt;&lt;/td&gt; <br/>&lt;/table&gt; <br/><br/>&nbsp;랑 도대체 어케 코딩 하느냐죠 ? <br/><br/>솔직히 코딩은 a.php 가 편합니다. <br/>&lt;? ?&gt; 를 한번 만 쓰니까 효율적일 수 있습니당.. <br/><br/>그러나 아무리 아무리 PHP가 빠르다고 해도 HTML 이 더 빠릅니당.. !!! <br/><br/>쿠쿠쿠 <br/><br/>b.php 처럼 코딩 하는 습관을 가지세용 ^^ <br/><br/>========================================================================== <br/>★ zend cache , APC ,Bware 캐쉬 비교 <br/>Zend cache &gt; APC &gt; Bware <br/><br/>zend cache 는 캐쉬 입니다. 울나라에서 포탈에서도 몇군데 사용하죠. <br/>PHP 프로그램 변환 없이 속도를 빠르게 해 줍니다. ^^ <br/><br/>zend cache 를 살 돈이 없으시다구용? <br/>그러면 APC 나 zend optimizer 를 반드쉬 설치 하세용 !! <br/><br/>■ 그런디 Zend Cache 만한 무료 캐쉬가 나왔다고 합니당...^^ <br/><A HREF="http://www.php" TARGET='_blank'>http://www.php</A> -accelerator.co.uk/index.php ; <br/><br/><br/>========================================================================== <br/>★ ereg_replace , preg_replace 정규표현식 <br/>ereg_replace () 가 장난 아니게 느림다. <br/>40개 정도 변환 하는데 1초나 걸려요.preg_replace 는 0.3초 정도요. <br/><br/>되도록이면 preg_replace() 를 사용하세요 !!! <br/><br/><A HREF="http://www.php.net/preg_replace" TARGET='_blank'>www.php.net/preg_replace</A> <br/><br/><br/>========================================================================== <br/>★ foreach , list 함수 속도 차이 35% <br/><br/>foreach($string as $a);&nbsp; &gt;&gt;&gt;&nbsp; while(list(,$a) = each($string)); <br/><br/>foreach() 를 사용하는 것이 35% 정도 빠릅니다...!! <br/><br/><br/>========================================================================== <br/>★mysql_connect Vs mysql_pconnect <br/><br/>서로 장단이 있다 합니다. <br/><br/>mysql_pconnect 가 더 빠르다고 합니다. <br/>persistant <br/><br/>메뉴얼에 영구적인 이렇게 되어 있으니까요.. <br/>일정시간 동안 mysql 을 열어 놓기 때문에, 다시 열 필요가 없어서 빠르다고 합니다. <br/><br/>단점은 계속 열기 때문에 메모리를 많이 잡아 먹슴당...^^ <br/>mysql_pconnect 경우는 최소 메모리가 1G 이상 되어야 사용하시는 것이 좋습니다. <br/><br/>========================================================================== <br/>★ 큰따옴표(") , 작은 따옴표(&#039;) <br/><br/>큰따옴표는 PHP가 파싱을 합니다. 그러나 작은 따옴표는 파싱을 하지 않습니다. <br/>작은 따옴표를 사용하시는 것이 빠릅니다. <br/><br/>코딩시 echo &#039; test &#039;.$aaa.&#039; tood &#039;; <br/>요런식으로 하시는 게 가장 빠름당 !! <br/><br/>========================================================================== <br/>★ mysql 데이터 저장 공간 크기 ? <br/><br/><br/>id int(11) unsigned NOT NULL auto_increment, <br/>&nbsp; bbs smallint(5) unsigned NOT NULL, <br/>&nbsp; lens mediumint(8) unsigned NOT NULL, <br/>&nbsp; <br/><br/>int 도 무자게 많슴당.. <br/>각각의 크기에 맞게 하는 것이 속도가 빨라 집니당 ^^ <br/><br/>not null 를 주는 것도 속도가 빨라 집니당.. <br/><br/>작은 사이트 조회수 경우 1만을 넘기도 힘듭니다. 그럴 경우 smallint 를 사용하시면 됩니다. <br/><br/>========================================================================== <br/>★ where 절에 모든 것은 인덱스를 걸어라 !!! <br/>mysql 에서 쿼리시에 where 절에 사용되는 비교의 칼럼은 반드쉬 인덱스를 거세용 !!! <br/><br/>mysql 인덱스 가 여러 분들의 게시판 속도를 업 시켜 줍니당 !! <br/><br/><br/>========================================================================== <br/>★메인페이지에서 속도를 빠르게 하려면, .htm 으로 만드는 것이 좋습니다. <br/><br/>그러니까..제 사이트 페이지 오른쪽 에는 모두 최신 게시물로 디비를 불러오는 부분 <br/>입니다. <br/><br/>디비 연결은 부하를 줄 수 있습니다. <br/><br/>그러니까..이예는 사이트가 상당히 활성화된 사이트일 경우 입니다. <br/><br/>하루에 2번 정도 .htm 으로 만들어 페이지를 업시키는 것이 좋습니다. <br/>아무리 PHP가 빨라도 HTML 보다는 빠르지 않습니다.. !!! <br/><br/>그러기 위해서는 ★cron 를 알아야 합니다 PHP강좌 게시판에서 cron 으로 검색하세용 !! <br/>윈도우 사용자는 멀 쓰는지 잘 모르겠슴당...아시면 답글 부탁&nbsp; ^^ <br/><br/><br/>========================================================================== <br/>★ 초보자 Vs 전문가 <br/><br/><A HREF="http://www.zend.com" TARGET='_blank'>www.zend.com</A> 에서 제가 2000년 5월에 퍼온건데용 ^^&nbsp; <br/>함 주석을 붙일까 해서용^^ <br/><br/><br/>Beginner vs Experienced&nbsp; <br/>Author:&nbsp; Boaz Yahav&nbsp; <br/>Date&nbsp; 23/05/2000&nbsp; <br/><br/>Beginner : echo "$var";&nbsp; <br/>Experienced : echo $var;&nbsp; <br/><br/><br/>Beginner:echo "&lt;a href=\" <A HREF="http://www.php.net" TARGET='_blank'>http://www.php.net</A>\"&gt;PHP&lt;/a&gt;";&nbsp; ; <br/>Experienced : ?&gt;&lt;a href=" <A HREF="http://www.php.net" TARGET='_blank'>http://www.php.net</A>"&gt;PHP&lt;/a&gt;&lt;?&nbsp; ... ?&gt;&nbsp; ; <br/><br/>◆ "(따옴표) 가 굉장히 중요한것이라는 한 대목이죵 ^^ <br/>전 보통의 경우 php 변수 값이 들어갈 경우는 초보자 처럼 쓰구요 ^^ 안들어 갈 경우 는 전문가 처럼 씀다. <br/><br/>Beginner : $a[0]=1; $a[1]=2; $a[2]=3;&nbsp; <br/>Experienced : $a = array(1,2,3, 1);&nbsp; <br/>둘다 사용하는 데요. 전문가 쪽이 편함다. ^^ <br/><br/>Beginner : if($a&gt;1) { $b=2; } else { $b=3; }&nbsp; <br/>Experienced : $b = ($a&gt;1) ? 2:3;&nbsp; <br/>요건 완존히 소스 어렵게 짜는 넘이 최고 라는 소리 같네용 ^^ <br/>전문가 쪽것은 C 언어 에서 배웠는데도 역시 전 if 씀다. ^^ <br/><br/>Beginner : $result=mysql_query(...);&nbsp; <br/>Experienced: $result=mysql_query(...) OR die&nbsp; <br/>&nbsp; &nbsp; &nbsp; &nbsp; (mysql_error());&nbsp; <br/><br/>요즘 들어 새삼 전문가 쪽으로 씀다.^^ <br/>보통의 경우 <br/><br/>$result=mysql_query(...)&nbsp; <br/>if (!$result) <br/>{ <br/>&nbsp;echo error()."&lt;P&gt;"; <br/>&nbsp;echo errno(); <br/>} <br/>이렇게 사용함다. ^^ <br/><br/>or 이 설명이고 no 가 에러 번호 일 검다. ^^ <br/><br/>========================================================================== <br/>★MySQL,ADODB,PHPLib,PEAR 벤치마킹&nbsp; <br/><br/>ADODB &gt; PHPlib &gt; PEAR <br/>&nbsp; <br/>MySQL&nbsp; &nbsp; 1.14&nbsp; &nbsp; &nbsp; - <br/>ADODB&nbsp; &nbsp; 1.45&nbsp; &nbsp; 27% <br/>PHPLib&nbsp; &nbsp; 1.60&nbsp; &nbsp; 40% <br/>PEAR&nbsp; &nbsp; 2.87&nbsp; &nbsp; 152% (fetchInto) <br/><br/>MySQL,ADODB,PHPLib,PEAR&nbsp; 는 모두 데이터베이스 인가요? 당근 아닙니다. <br/>MySQL만 데이터베이스 구요. <br/>ADODB,PHPLib,PEAR 는 PHP 프로그램 입니다. <br/><br/>3개 다 MySQL연결을 편하게 하는 클래스 프로그램 입니다. <br/>그런디 벤치 마킹 결과 MySQL 에서 직접 쿼리하는 것 다음으로 ADODB 가 뽑혔슴당 ^^ <br/><br/>PEAR 가 굉장히 늦군요. PEAR DB 나 ADODB 를 사용해 보았는데, 움..역시나 ADODB 가 좋군요. <br/>오라클, mysql , ms sql 연결시 1개의 API 만 사용할 수 있는 프로그램 들 이 PEAR 과 ADODB 입니당 ^^ <br/>========================================================================== <br/>★ 속도 테스트는 어케 하는가 ? microtime() 사용하면 됩니다. <br/><br/><br/>&lt;? <br/><br/>function pageTime($page) { <br/>&nbsp;$mstart = explode(" ", $m); <br/>&nbsp;$mend = explode(" ", microtime()); <br/>&nbsp;$mtime = ($mend[1] - $mstart[1]) + ($mend[0] - $mstart[0]); <br/><br/>&nbsp;echo " $m[1]&nbsp; $mend[1]&lt;P&gt;"; <br/>&nbsp;echo " $m[0]&nbsp; $mend[0]&lt;P&gt;"; <br/><br/>&nbsp;print("tood.net 페이지 로딩 시간 : " . $mtime . " microseconds"); <br/>} <br/>pageTime(basename($PHP_SELF)); <br/>?&gt; <br/>&nbsp; <br/>========================================================================== <br/>★ <br/><br/>========================================================================== <br/><br/>참고 사이트 <br/><A HREF="http://www.tood.net" TARGET='_blank'>http://www.tood.net</A> <br/><A HREF="http://www.zend.com" TARGET='_blank'>http://www.zend.com</A> <br/><A HREF="http://www.php.net" TARGET='_blank'>http://www.php.net</A> <br/><A HREF="http://www.php.lt/benchmark/phpbench.php" TARGET='_blank'>http://www.php.lt/benchmark/phpbench.php</A> <br/><A HREF="http://www.phpbuilder.com" TARGET='_blank'>http://www.phpbuilder.com</A> <br/><A HREF="http://www.phpbuilder.com/columns/piergiorgio20010321.php3?print_mode=1" TARGET='_blank'>http://www.phpbuilder.com/columns/piergiorgio20010321.php3?print_mode=1</A>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Tue, 30 Jan 2007 09:04:57 -0700</dc:date>
</item>
<item>
<title>Ajax 마스터하기</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=20</link>
<description><![CDATA[웹 사이트를 구현하는 생선적인 방식인 Ajax 이해하기 <br/><br/>난이도 : 초급 <br/><br/>Brett McLaughlin, Author and Editor, O&#039;Reilly Media Inc. <br/><br/><br/>2006 년 5 월 29 일 <br/>2006 년 12 월 12 일 수정 <br/><br/>1~8까지 한글 번역되어 있습니다.]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Tue, 30 Jan 2007 08:49:53 -0700</dc:date>
</item>
<item>
<title>simple database class</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=19</link>
<description><![CDATA[This simple class is what I use all the time when connecting to database using PHP and MySql.









-------------------------------------------------------------------------------------------

<pre>
// db connection class
class MySql
{
	var $dbHost;	// dbHost
	var $dbUser;	// db user
	var $dbPass;	// db password
	var $dbName;	// db name
	var $dbConn;	// db connection
	var $dbConnErr;	// db connection error

	// constructor
	function MySql($dbHost, $dbUser, $dbPass, $dbName)
	{
		$this->dbHost = $dbHost;
		$this->dbUser = $dbUser;
		$this->dbPass = $dbPass;
		$this->dbName = $dbName;
		$this->connectToDb();
	}

	// establish db connection
	function connectToDb()
	{
		// make connection to mysql server
		if (!$this->dbConn = @mysql_connect($this->dbHost, $this->dbUser, $this->dbPass))
		{
			trigger_error("Could not connect to server.");
			$this->dbConnErr = true;
		}
		else if (!@mysql_select_db($this->dbName, $this->dbConn))
		{
			trigger_error("Could not select db.");
			$this->dbConnErr = true;
		}
	}

	// query function that returns an MySqlResult object
	function &query($sql)
	{
		if (!$queryResource = mysql_query($sql, $this->dbConn))
		{
			trigger_error("Query failed: ".mysql_error($this->dbConn)."<br>SQL: ".$sql);
		}
		
		return new MySqlResult($this, $queryResource);
	}

	// checks db errors
	function isError()
	{
		if ($this->dbConnErr)
		{
			return true;
		}
		
		$error = mysql_error($this->dbConn);
	
		if (empty($error))
		{
			return false;
		}
		else
		{
			return true;
		}
	}

}



// query result class
class MySqlResult
{
	var $mysql;	// instance of db connection
	var $result;	// query result

	// constructor
	function MySqlResult(&$mysql, $result)	// object $mysql
	{
		$this->mysql = &$mysql;
		$this->result = $result;
	}

	// fetches a row from result (without MYSQL_ASSOC)
	function fetch()
	{
		if ($row = mysql_fetch_array($this->result))
		{
			return $row;
		}
		else if ($this->numRows() > 0)
		{
			mysql_data_seek($this->result, 0);
			return false;
		}
		else
		{
			return false;
		}
	}

	// fetches a row from result (with MYSQL_ASSOC)
	function fetchA()
	{
		if ($row = mysql_fetch_array($this->result, MYSQL_ASSOC))
		{
			return $row;
		}
		else if ($this->numRows() > 0)
		{
			mysql_data_seek($this->result, 0);
			return false;
		}
		else
		{
			return false;
		}
	}

	// count rows
	function numRows()
	{
		return mysql_num_rows($this->result);
	}

	// get ID of the last row inserted
	function insertId()
	{
		return mysql_insert_id($this->mysql->dbConn);
	}

	// get number of affected rows
	function affectedRows()
	{
		return mysql_affected_rows($this->mysql->dbConn);
	}

	// checks db errors
	function isError()
	{
		return $this->mysql->isError();
	}
}
</pre>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Fri, 19 Jan 2007 09:43:10 -0700</dc:date>
</item>
<item>
<title>MySQL Sub Queries</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=17</link>
<description><![CDATA[<br/><br/>If we move on to a more complicated (and arguably more useful) example, we&#039;ll start to see the power of subqueries. Let&#039;s find out what the highest number of official languages in any country is: <br/><br/>&nbsp; /* 1 */<br/>&nbsp; SELECT MAX(tbl.nr) AS nr<br/>&nbsp; FROM <br/>&nbsp; &nbsp; (<br/>&nbsp; &nbsp; &nbsp; /* 2 */<br/>&nbsp; &nbsp; &nbsp; SELECT countrycode, COUNT(*) AS nr <br/>&nbsp; &nbsp; &nbsp; FROM CountryLanguage <br/>&nbsp; &nbsp; &nbsp; WHERE isofficial=&#039;T&#039; <br/>&nbsp; &nbsp; &nbsp; GROUP BY countrycode<br/>&nbsp; &nbsp; ) AS tbl;<br/><br/>&nbsp; +---------+<br/>&nbsp; | MAX(nr) |<br/>&nbsp; +---------+<br/>&nbsp; |&nbsp; &nbsp; &nbsp;  4 |<br/>&nbsp; +---------+<br/>Again, those of you who are MySQL experts might note that the same answer could be found with an ORDER BY and LIMIT. Again, I have to alias the subquery part to something, and I chose AS tbl. Let&#039;s do something that couldn&#039;t be done easily without subqueries: Let&#039;s get the information for those countries with the the highest number of official languages: <br/><br/>&nbsp; /* 1 */<br/>&nbsp; SELECT name, population, headofstate, top.nr<br/>&nbsp; FROM<br/>&nbsp; &nbsp; Country,<br/>&nbsp; &nbsp; (<br/>&nbsp; &nbsp; &nbsp; /* 2 */<br/>&nbsp; &nbsp; &nbsp; SELECT countrycode, COUNT(*) AS nr<br/>&nbsp; &nbsp; &nbsp; FROM CountryLanguage<br/>&nbsp; &nbsp; &nbsp; WHERE isofficial=&#039;T&#039;<br/>&nbsp; &nbsp; &nbsp; GROUP BY countrycode<br/>&nbsp; &nbsp; &nbsp; HAVING nr=(<br/>&nbsp; &nbsp; &nbsp; &nbsp; /* 3 */<br/>&nbsp; &nbsp; &nbsp; &nbsp; SELECT MAX(summary.nr_official_languages)<br/>&nbsp; &nbsp; &nbsp; &nbsp; FROM <br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* 4 */<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SELECT countrycode, COUNT(*) AS nr_official_languages<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FROM CountryLanguage <br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WHERE isofficial=&#039;T&#039; <br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GROUP BY countrycode<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) AS summary<br/>&nbsp; &nbsp; &nbsp; &nbsp; )<br/>&nbsp; &nbsp; ) as top<br/>&nbsp; WHERE Country.code=top.countrycode<br/><br/>&nbsp; +--------------+------------+-------------+----+<br/>&nbsp; | name&nbsp; &nbsp; &nbsp; &nbsp;  | population | headofstate | nr |<br/>&nbsp; +--------------+------------+-------------+----+<br/>&nbsp; | Switzerland&nbsp; |&nbsp; &nbsp; 7160400 | Adolf Ogi&nbsp;  |&nbsp; 4 |<br/>&nbsp; | South Africa |&nbsp;  40377000 | Thabo Mbeki |&nbsp; 4 |<br/>&nbsp; +--------------+------------+-------------+----+<br/>This query is not so simple. It nests four SELECT statements one inside the other, to accomplish a somewhat complex result. I have added comments to the statement of the form /* 1 */ to mark each statement, so that we can break the query down logically. If we look at each of the individual queries, by number, and in reverse order, which I find easiest (and is also the order in which MySQL must solve the query): <br/><br/>4. This SELECT finds all countries and the number of official languages for each. We&#039;re interested in what the maximum number is, and there may be more than one with the same maximum.&nbsp; <br/>3. This SELECT finds the maximum of nr_official_languages from SELECT #4. There isn&#039;t an SQL-standard way of getting the countrycode column for the max at the same time, since there may be more than one.&nbsp; <br/>2. In this SELECT we match up the country codes based on the number of official languages.&nbsp; <br/>1. Finally, we can JOIN the result against the Country table to find the country information about the matching countries.&nbsp; <br/><br/>I hope you&#039;ve learned something, and will do some of your own reading about subqueries. In the next article of the series, we&#039;ll discuss Correlation, ANY, and EXISTS. <br/><br/>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Wed, 15 Nov 2006 10:22:49 -0700</dc:date>
</item>
<item>
<title>N-Tier(Three-Tier) Computing</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=16</link>
<description><![CDATA[<img src=http://upload.wikimedia.org/wikipedia/en/6/66/Overview_of_a_three-tier_application.png>

N-Tier Computing (Three-Tier Computing)

In computing, Three-tier is a client-server architecture in which the user interface, functional process logic ("business rules"), data storage and data access are developed and maintained as independent modules, most often on separate platforms. The term "three-tier" or "three-layer", as well as the concept of multitier architectures, seems to have originated within Rational Software.

The three-tier model is considered to be a software architecture and a software design pattern.

Apart from the usual advantages of modular software with well defined interfaces, the three-tier architecture is intended to allow any of the three tiers to be upgraded or replaced independently as requirements or technology change. For example, a change of operating system from Microsoft Windows to Unix would only affect the user interface code.

Typically, the user interface runs on a desktop PC or workstation and uses a standard graphical user interface, functional process logic may consist of one or more separate modules running on a workstation or application server, and an RDBMS on a database server or mainframe contains the data storage logic. The middle tier may be multi-tiered itself (in which case the overall architecture is called an "n-tier architecture").

It seems similar, although defined in slightly different terms, to the Model-view-controller concept and the pipes and filters concept.


<b>Web services usage</b>

In the Web service field, three-tier is used to refer to Websites, often Electronic commerce websites, which are built using three tiers:

1. A front end Web server serving static content 
2. A middle dynamic content processing and generation level Application server, for example Java EE platform. 
3. A back end Database, comprising both data sets and the Database management system or RDBMS software that manages and provides access to the data. ]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Tue, 02 May 2006 17:08:12 -0700</dc:date>
</item>
<item>
<title>10 Tips for Writing High-Performance Web Applications</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=15</link>
<description><![CDATA[ASP.NET
10 Tips for Writing High-Performance Web Applications

Rob HowardPrint

--------------------------------------------------------------------------------
This article discusses:
- Common ASP.NET performance myths
- Useful performance tips and tricks for ASP.NET
- Suggestions for working with a database from ASP.NET
- Caching and background processing with ASP.NET
 
This article uses the following technologies:
- ASP.NET, .NET Framework, IIS
--------------------------------------------------------------------------------

Contents

Performance on the Data Tier
Tip 1&#8212;Return Multiple Resultsets
Tip 2&#8212;Paged Data Access
Tip 3&#8212;Connection Pooling
Tip 4&#8212;ASP.NET Cache API
Tip 5&#8212;Per-Request Caching
Tip 6&#8212;Background Processing
Tip 7&#8212;Page Output Caching and Proxy Servers
Tip 8&#8212;Run IIS 6.0 (If Only for Kernel Caching)
Tip 9&#8212;Use Gzip Compression
Tip 10&#8212;Server Control View State
Conclusion

-------------------------------------------------------------------------------


Writing a Web application with ASP.NET is unbelievably easy. So easy, many developers don't take the time to structure their applications for great performance. In this article, I'm going to present 10 tips for writing high-performance Web apps. I'm not limiting my comments to ASP.NET applications because they are just one subset of Web applications. This article won't be the definitive guide for performance-tuning Web applications&#8212;an entire book could easily be devoted to that. Instead, think of this as a good place to start.

Before becoming a workaholic, I used to do a lot of rock climbing. Prior to any big climb, I'd review the route in the guidebook and read the recommendations made by people who had visited the site before. But, no matter how good the guidebook, you need actual rock climbing experience before attempting a particularly challenging climb. Similarly, you can only learn how to write high-performance Web applications when you're faced with either fixing performance problems or running a high-throughput site.

My personal experience comes from having been an infrastructure Program Manager on the ASP.NET team at Microsoft, running and managing www.asp.net, and helping architect Community Server, which is the next version of several well-known ASP.NET applications (ASP.NET Forums, .Text, and nGallery combined into one platform). I'm sure that some of the tips that have helped me will help you as well.

You should think about the separation of your application into logical tiers. You might have heard of the term 3-tier (or n-tier) physical architecture. These are usually prescribed architecture patterns that physically divide functionality across processes and/or hardware. As the system needs to scale, more hardware can easily be added. There is, however, a performance hit associated with process and machine hopping, thus it should be avoided. So, whenever possible, run the ASP.NET pages and their associated components together in the same application.

Because of the separation of code and the boundaries between tiers, using Web services or remoting will decrease performance by 20 percent or more.

The data tier is a bit of a different beast since it is usually better to have dedicated hardware for your database. However, the cost of process hopping to the database is still high, thus performance on the data tier is the first place to look when optimizing your code.

Before diving in to fix performance problems in your applications, make sure you profile your applications to see exactly where the problems lie. Key performance counters (such as the one that indicates the percentage of time spent performing garbage collections) are also very useful for finding out where applications are spending the majority of their time. Yet the places where time is spent are often quite unintuitive.

There are two types of performance improvements described in this article: large optimizations, such as using the ASP.NET Cache, and tiny optimizations that repeat themselves. These tiny optimizations are sometimes the most interesting. You make a small change to code that gets called thousands and thousands of times. With a big optimization, you might see overall performance take a large jump. With a small one, you might shave a few milliseconds on a given request, but when compounded across the total requests per day, it can result in an enormous improvement.


<b>Performance on the Data Tier</b>

When it comes to performance-tuning an application, there is a single litmus test you can use to prioritize work: does the code access the database? If so, how often? Note that the same test could be applied for code that uses Web services or remoting, too, but I'm not covering those in this article.

If you have a database request required in a particular code path and you see other areas such as string manipulations that you want to optimize first, stop and perform your litmus test. Unless you have an egregious performance problem, your time would be better utilized trying to optimize the time spent in and connected to the database, the amount of data returned, and how often you make round-trips to and from the database.

With that general information established, let's look at ten tips that can help your application perform better. I'll begin with the changes that can make the biggest difference.



<b>Tip 1&#8212;Return Multiple Resultsets</b>

Review your database code to see if you have request paths that go to the database more than once. Each of those round-trips decreases the number of requests per second your application can serve. By returning multiple resultsets in a single database request, you can cut the total time spent communicating with the database. You'll be making your system more scalable, too, as you'll cut down on the work the database server is doing managing requests.

While you can return multiple resultsets using dynamic SQL, I prefer to use stored procedures. It's arguable whether business logic should reside in a stored procedure, but I think that if logic in a stored procedure can constrain the data returned (reduce the size of the dataset, time spent on the network, and not having to filter the data in the logic tier), it's a good thing.

Using a SqlCommand instance and its ExecuteReader method to populate strongly typed business classes, you can move the resultset pointer forward by calling NextResult. Figure 1 shows a sample conversation populating several ArrayLists with typed classes. Returning only the data you need from the database will additionally decrease memory allocations on your server.



<b>Tip 2&#8212;Paged Data Access</b>

The ASP.NET DataGrid exposes a wonderful capability: data paging support. When paging is enabled in the DataGrid, a fixed number of records is shown at a time. Additionally, paging UI is also shown at the bottom of the DataGrid for navigating through the records. The paging UI allows you to navigate backwards and forwards through displayed data, displaying a fixed number of records at a time.

There's one slight wrinkle. Paging with the DataGrid requires all of the data to be bound to the grid. For example, your data layer will need to return all of the data and then the DataGrid will filter all the displayed records based on the current page. If 100,000 records are returned when you're paging through the DataGrid, 99,975 records would be discarded on each request (assuming a page size of 25). As the number of records grows, the performance of the application will suffer as more and more data must be sent on each request.

One good approach to writing better paging code is to use stored procedures. Figure 2 shows a sample stored procedure that pages through the Orders table in the Northwind database. In a nutshell, all you're doing here is passing in the page index and the page size. The appropriate resultset is calculated and then returned.

In Community Server, we wrote a paging server control to do all the data paging. You'll see that I am using the ideas discussed in Tip 1, returning two resultsets from one stored procedure: the total number of records and the requested data.

The total number of records returned can vary depending on the query being executed. For example, a WHERE clause can be used to constrain the data returned. The total number of records to be returned must be known in order to calculate the total pages to be displayed in the paging UI. For example, if there are 1,000,000 total records and a WHERE clause is used that filters this to 1,000 records, the paging logic needs to be aware of the total number of records to properly render the paging UI.



<b>Tip 3&#8212;Connection Pooling</b>

Setting up the TCP connection between your Web application and SQL Server™ can be an expensive operation. Developers at Microsoft have been able to take advantage of connection pooling for some time now, allowing them to reuse connections to the database. Rather than setting up a new TCP connection on each request, a new connection is set up only when one is not available in the connection pool. When the connection is closed, it is returned to the pool where it remains connected to the database, as opposed to completely tearing down that TCP connection.

Of course you need to watch out for leaking connections. Always close your connections when you're finished with them. I repeat: no matter what anyone says about garbage collection within the Microsoft? .NET Framework, always call Close or Dispose explicitly on your connection when you are finished with it. Do not trust the common language runtime (CLR) to clean up and close your connection for you at a predetermined time. The CLR will eventually destroy the class and force the connection closed, but you have no guarantee when the garbage collection on the object will actually happen.

To use connection pooling optimally, there are a couple of rules to live by. First, open the connection, do the work, and then close the connection. It's okay to open and close the connection multiple times on each request if you have to (optimally you apply Tip 1) rather than keeping the connection open and passing it around through different methods. Second, use the same connection string (and the same thread identity if you're using integrated authentication). If you don't use the same connection string, for example customizing the connection string based on the logged-in user, you won't get the same optimization value provided by connection pooling. And if you use integrated authentication while impersonating a large set of users, your pooling will also be much less effective. The .NET CLR data performance counters can be very useful when attempting to track down any performance issues that are related to connection pooling.

Whenever your application is connecting to a resource, such as a database, running in another process, you should optimize by focusing on the time spent connecting to the resource, the time spent sending or retrieving data, and the number of round-trips. Optimizing any kind of process hop in your application is the first place to start to achieve better performance.

The application tier contains the logic that connects to your data layer and transforms data into meaningful class instances and business processes. For example, in Community Server, this is where you populate a Forums or Threads collection, and apply business rules such as permissions; most importantly it is where the Caching logic is performed.



<b>Tip 4&#8212;ASP.NET Cache API</b>

One of the very first things you should do before writing a line of application code is architect the application tier to maximize and exploit the ASP.NET Cache feature.

If your components are running within an ASP.NET application, you simply need to include a reference to System.Web.dll in your application project. When you need access to the Cache, use the HttpRuntime.Cache property (the same object is also accessible through Page.Cache and HttpContext.Cache).

There are several rules for caching data. First, if data can be used more than once it's a good candidate for caching. Second, if data is general rather than specific to a given request or user, it's a great candidate for the cache. If the data is user- or request-specific, but is long lived, it can still be cached, but may not be used as frequently. Third, an often overlooked rule is that sometimes you can cache too much. Generally on an x86 machine, you want to run a process with no higher than 800MB of private bytes in order to reduce the chance of an out-of-memory error. Therefore, caching should be bounded. In other words, you may be able to reuse a result of a computation, but if that computation takes 10 parameters, you might attempt to cache on 10 permutations, which will likely get you into trouble. One of the most common support calls for ASP.NET is out-of-memory errors caused by overcaching, especially of large datasets.


<img src=http://msdn.microsoft.com/msdnmag/issues/05/01/ASPNETPerformance/fig03.gif>
Figure 3 ASP.NET Cache


There are a several great features of the Cache that you need to know. The first is that the Cache implements a least-recently-used algorithm, allowing ASP.NET to force a Cache purge&#8212;automatically removing unused items from the Cache&#8212;if memory is running low. Secondly, the Cache supports expiration dependencies that can force invalidation. These include time, key, and file. Time is often used, but with ASP.NET 2.0 a new and more powerful invalidation type is being introduced: database cache invalidation. This refers to the automatic removal of entries in the cache when data in the database changes. For more information on database cache invalidation, see Dino Esposito's Cutting Edge column in the July 2004 issue of MSDN?Magazine. For a look at the architecture of the cache, see Figure 3.



<b>Tip 5&#8212;Per-Request Caching</b>

Earlier in the article, I mentioned that small improvements to frequently traversed code paths can lead to big, overall performance gains. One of my absolute favorites of these is something I've termed per-request caching.

Whereas the Cache API is designed to cache data for a long period or until some condition is met, per-request caching simply means caching the data for the duration of the request. A particular code path is accessed frequently on each request but the data only needs to be fetched, applied, modified, or updated once. This sounds fairly theoretical, so let's consider a concrete example.

In the Forums application of Community Server, each server control used on a page requires personalization data to determine which skin to use, the style sheet to use, as well as other personalization data. Some of this data can be cached for a long period of time, but some data, such as the skin to use for the controls, is fetched once on each request and reused multiple times during the execution of the request.

To accomplish per-request caching, use the ASP.NET HttpContext. An instance of HttpContext is created with every request and is accessible anywhere during that request from the HttpContext.Current property. The HttpContext class has a special Items collection property; objects and data added to this Items collection are cached only for the duration of the request. Just as you can use the Cache to store frequently accessed data, you can use HttpContext.Items to store data that you'll use only on a per-request basis. The logic behind this is simple: data is added to the HttpContext.Items collection when it doesn't exist, and on subsequent lookups the data found in HttpContext.Items is simply returned.



<b>Tip 6&#8212;Background Processing</b>

The path through your code should be as fast as possible, right? There may be times when you find yourself performing expensive tasks on each request or once every n requests. Sending out e-mails or parsing and validation of incoming data are just a few examples.

When tearing apart ASP.NET Forums 1.0 and rebuilding what became Community Server, we found that the code path for adding a new post was pretty slow. Each time a post was added, the application first needed to ensure that there were no duplicate posts, then it had to parse the post using a "badword" filter, parse the post for emoticons, tokenize and index the post, add the post to the moderation queue when required, validate attachments, and finally, once posted, send e-mail notifications out to any subscribers. Clearly, that's a lot of work.

It turns out that most of the time was spent in the indexing logic and sending e-mails. Indexing a post was a time-consuming operation, and it turned out that the built-in System.Web.Mail functionality would connect to an SMTP server and send the e-mails serially. As the number of subscribers to a particular post or topic area increased, it would take longer and longer to perform the AddPost function.

Indexing e-mail didn't need to happen on each request. Ideally, we wanted to batch this work together and index 25 posts at a time or send all the e-mails every five minutes. We decided to use the same code I had used to prototype database cache invalidation for what eventually got baked into Visual Studio? 2005.

The Timer class, found in the System.Threading namespace, is a wonderfully useful, but less well-known class in the .NET Framework, at least for Web developers. Once created, the Timer will invoke the specified callback on a thread from the ThreadPool at a configurable interval. This means you can set up code to execute without an incoming request to your ASP.NET application, an ideal situation for background processing. You can do work such as indexing or sending e-mail in this background process too.

There are a couple of problems with this technique, though. If your application domain unloads, the timer instance will stop firing its events. In addition, since the CLR has a hard gate on the number of threads per process, you can get into a situation on a heavily loaded server where timers may not have threads to complete on and can be somewhat delayed. ASP.NET tries to minimize the chances of this happening by reserving a certain number of free threads in the process and only using a portion of the total threads for request processing. However, if you have lots of asynchronous work, this can be an issue.

There is not enough room to go into the code here, but you can download a digestible sample at www.rob-howard.net. Just grab the slides and demos from the Blackbelt TechEd 2004 presentation.



<b>Tip 7&#8212;Page Output Caching and Proxy Servers</b>

ASP.NET is your presentation layer (or should be); it consists of pages, user controls, server controls (HttpHandlers and HttpModules), and the content that they generate. If you have an ASP.NET page that generates output, whether HTML, XML, images, or any other data, and you run this code on each request and it generates the same output, you have a great candidate for page output caching.

By simply adding this line to the top of your page 

<%@ Page OutputCache VaryByParams="none" Duration="60" %> 

you can effectively generate the output for this page once and reuse it multiple times for up to 60 seconds, at which point the page will re-execute and the output will once be again added to the ASP.NET Cache. This behavior can also be accomplished using some lower-level programmatic APIs, too. There are several configurable settings for output caching, such as the VaryByParams attribute just described. VaryByParams just happens to be required, but allows you to specify the HTTP GET or HTTP POST parameters to vary the cache entries. For example, default.aspx?Report=1 or default.aspx?Report=2 could be output-cached by simply setting VaryByParam="Report". Additional parameters can be named by specifying a semicolon-separated list.

Many people don't realize that when the Output Cache is used, the ASP.NET page also generates a set of HTTP headers that downstream caching servers, such as those used by the Microsoft Internet Security and Acceleration Server or by Akamai. When HTTP Cache headers are set, the documents can be cached on these network resources, and client requests can be satisfied without having to go back to the origin server.

Using page output caching, then, does not make your application more efficient, but it can potentially reduce the load on your server as downstream caching technology caches documents. Of course, this can only be anonymous content; once it's downstream, you won't see the requests anymore and can't perform authentication to prevent access to it.



<b>Tip 8&#8212;Run IIS 6.0 (If Only for Kernel Caching)</b>

If you're not running IIS 6.0 (Windows Server™ 2003), you're missing out on some great performance enhancements in the Microsoft Web server. In Tip 7, I talked about output caching. In IIS 5.0, a request comes through IIS and then to ASP.NET. When caching is involved, an HttpModule in ASP.NET receives the request, and returns the contents from the Cache.

If you're using IIS 6.0, there is a nice little feature called kernel caching that doesn't require any code changes to ASP.NET. When a request is output-cached by ASP.NET, the IIS kernel cache receives a copy of the cached data. When a request comes from the network driver, a kernel-level driver (no context switch to user mode) receives the request, and if cached, flushes the cached data to the response, and completes execution. This means that when you use kernel-mode caching with IIS and ASP.NET output caching, you'll see unbelievable performance results. At one point during the Visual Studio 2005 development of ASP.NET, I was the program manager responsible for ASP.NET performance. The developers did the magic, but I saw all the reports on a daily basis. The kernel mode caching results were always the most interesting. The common characteristic was network saturation by requests/responses and IIS running at about five percent CPU utilization. It was amazing! There are certainly other reasons for using IIS 6.0, but kernel mode caching is an obvious one.



<b>Tip 9&#8212;Use Gzip Compression</b>

While not necessarily a server performance tip (since you might see CPU utilization go up), using gzip compression can decrease the number of bytes sent by your server. This gives the perception of faster pages and also cuts down on bandwidth usage. Depending on the data sent, how well it can be compressed, and whether the client browsers support it (IIS will only send gzip compressed content to clients that support gzip compression, such as Internet Explorer 6.0 and Firefox), your server can serve more requests per second. In fact, just about any time you can decrease the amount of data returned, you will increase requests per second.

The good news is that gzip compression is built into IIS 6.0 and is much better than the gzip compression used in IIS 5.0. Unfortunately, when attempting to turn on gzip compression in IIS 6.0, you may not be able to locate the setting on the properties dialog in IIS. The IIS team built awesome gzip capabilities into the server, but neglected to include an administrative UI for enabling it. To enable gzip compression, you have to spelunk into the innards of the XML configuration settings of IIS 6.0 (which isn't for the faint of heart). By the way, the credit goes to Scott Forsyth of OrcsWeb who helped me figure this out for the www.asp.net severs hosted by OrcsWeb.

Rather than include the procedure in this article, just read the article by Brad Wilson at IIS6 Compression. There's also a Knowledge Base article on enabling compression for ASPX, available at Enable ASPX Compression in IIS. It should be noted, however, that dynamic compression and kernel caching are mutually exclusive on IIS 6.0 due to some implementation details.



<b>Tip 10&#8212;Server Control View State</b>

View state is a fancy name for ASP.NET storing some state data in a hidden input field inside the generated page. When the page is posted back to the server, the server can parse, validate, and apply this view state data back to the page's tree of controls. View state is a very powerful capability since it allows state to be persisted with the client and it requires no cookies or server memory to save this state. Many ASP.NET server controls use view state to persist settings made during interactions with elements on the page, for example, saving the current page that is being displayed when paging through data.

There are a number of drawbacks to the use of view state, however. First of all, it increases the total payload of the page both when served and when requested. There is also an additional overhead incurred when serializing or deserializing view state data that is posted back to the server. Lastly, view state increases the memory allocations on the server.

Several server controls, the most well known of which is the DataGrid, tend to make excessive use of view state, even in cases where it is not needed. The default behavior of the ViewState property is enabled, but if you don't need it, you can turn it off at the control or page level. Within a control, you simply set the EnableViewState property to false, or you can set it globally within the page using this setting: 

<%@ Page EnableViewState="false" %>

If you are not doing postbacks in a page or are always regenerating the controls on a page on each request, you should disable view state at the page level.



<b>Conclusion</b>

I've offered you some tips that I've found useful for writing high-performance ASP.NET applications. As I mentioned at the beginning of this article, this is more a preliminary guide than the last word on ASP.NET performance. (More information on improving the performance of ASP.NET apps can be found at Improving ASP.NET Performance.) Only through your own experience can you find the best way to solve your unique performance problems. However, during your journey, these tips should provide you with good guidance. In software development, there are very few absolutes; every application is unique.]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Tue, 02 May 2006 17:04:45 -0700</dc:date>
</item>
<item>
<title>[ASP.NET] Another Server.Tranfer problem</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=14</link>
<description><![CDATA[Another Server.Tranfer problem.
There are lots many intricacies of .NET that most of us who work on it are unaware of. It is the obvious truth but time and time again, the CLR proves that to you by taxing your brain with weird results and behaviour and makes you think about your coding pattern again ! Recently, one of my team mates got stuck with a really weird Server.Transfer problem and it drove us crazy trying to even find out the problem. Irony it seems that the delicate problem has been encountered by so many people and everyone have been cribbing about it in many forums. I tried to replicate the problem with a simple Web App and guess what, within minutes, my computer was spitting out the same error message too !!! 
 
Here's the situation : 
 
Just use this code below ... It is a cooked up code but the funda is that whenever you have a Server.Transfer in a try catch block, after some kind of code, or rather preprocessing, then the Server.Transfer will throw up an exception “Thread was being aborted.” Well because we have a Catch that watches over these exceptions, eventhough the exception occurs after the transfer, the Catch block is executed unnecessarily and hence the actual code gets buggered ... This was one major pain in one of our projects recently and took us quite a while to sort it out ! 
 
Warning : Dont get messed up with such code. 
 
 
   public class WebForm1 : System.Web.UI.Page
   {
      protected System.Web.UI.WebControls.Button Button1;
      public static bool Diversion = false ;
 
      private void Button1_Click(object sender, System.EventArgs e)
      {
          try
          {
               if(Diversion)
               {
                  Diversion = false ;
                  Server.Transfer("Test1.aspx") ;
               }
               else
               {
                  Diversion = true ;
                  Server.Transfer("Test2.aspx") ;
               }
         }
         catch(Exception err)
         {
            Response.Write("Error Message : " + err.Message);
            if(!Diversion)
            {
                  Server.Transfer("Error.aspx") ;
                  Diversion = true ;
            }
         }
      }
 
      override protected void OnInit(EventArgs e)
      { 
            this.Button1.Click += new System.EventHandler(this.Button1_Click);
            this.Load += new System.EventHandler(this.Page_Load);
 
            base.OnInit(e);
      }
   }
 
 
One thing to remember about SmartNavigation is how SmartNavigation works. It takes postbacks and renders all the changed items to a hidden IFRAME-x, then replaces all the innerHTML control elements on the page with the results. This is what gives the illusion of a page that doesn't "jump" when reloaded. Server.Transfer() executes the referred page in the current context and does not actually readdress to it. It just clears the output buffer and executes another page producing output in the same buffer. Watch out for such details which can be important while doing such operations !
 
The workaround for this is to put the Server.Tranfer outside the try-catch block ( which is the obvious answer isn't it ?! ) but oh well the elegant solution for that is to catch the System.Threading.ThreadAbortException and handle it appropriately !! 
 
catch(ThreadAbortException e)
{
    throw e;
    // or ignore ;)
}
This problem occurs in the Server.Transfer method because the method internally calls Response.End because of which the thread which has been aborted can no longer serve the consequent execution commands and hence the CLR throws up the exception.

According to one of the MS KB articles, to work around this problem, use the Server.Execute method instead of Server.Transfer. This will solve the issue ! Well this works and solves the problem but another important fact has to be remembered here. The Server.Execute function accepts a URL parameter, stops execution of the current page (where the call to the function is made), and transfers the current environment to the new page. When that new page finishes execution, then control returns to the calling page just after where the Server.Execute was called. (Server.Transfer works the same way but however, upon completion of the execution of the new page, processing ends and Response.End is called for the current context !) 

Well that's it for now about Page navigation. Still learning about this and will be glad to hear any other facts that i have missed out.

Happy coding.


p.s. :
be sure to use
<b>using System.Threading;</b>]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Sun, 23 Apr 2006 13:53:35 -0700</dc:date>
</item>
<item>
<title>[ASP.NET] Server.Transfer vs Response.Redirect</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=13</link>
<description><![CDATA[Server.Transfer vs Response.Redirect:<br/><br/>A common misconception is the difference between Server.Transfer and Response.Redirect in ASP.NET applications. Redirect and Transfer both cause a new page to be processed, but the interaction between the client (web browser) and server (ASP.NET) is different in each situation. <br/><br/>Redirect: A redirect is just a suggestion &#8211; it’s like saying to the client “Hey, you might want to look at this”. All you tell the client is the new URL to look at, and if they comply, they do a second request for the new URL. <br/><br/>If you want to pass state from the source page to the new page, you have to pass it either on the URL (such as a database key, or message string), or you can store it in the Session object (caveat: there may be more than one browser window, and they’ll all use the same session object). <br/><br/>e.g. Redirect to the new.aspx page, passing an ID on the query string. "true" stops processing the current page: <br/><br/><br/>Response.Redirect("new.aspx?id=34", true);<br/>&nbsp;<br/><br/><br/><br/>Transfer: A transfer happens without the client knowing &#8211; it’s the equivalent of a client requesting one page, but being given another. As far as the client knows, they are still visiting the original URL. <br/><br/>Sharing state between pages is much easier using Server.Transfer &#8211; you can put values into the Context.Items dictionary, which is similar to Session and Application, except that it lasts only for the current request. (search for HttpContext in MSDN). The page receiving postback can process data, store values in the Context, and then Transfer to a page that uses the values. <br/><br/>e.g. Store a message in the context dictionary, and transfer to the default.aspx page (which can then display the message): <br/><br/><br/>Context.Items["Message"] = "Your password was changed successfully";<br/>Server.Transfer("default.aspx");<br/>&nbsp;<br/><br/><br/><br/>Caveats: <br/><br/><br/>Response.Redirect is more user-friendly, as the site visitor can bookmark the page that they are redirected to. <br/>Transferred pages appear to the client as a different url than they really are. This means that things like relative links / image paths may not work if you transfer to a page from a different directory. <br/>Server.Transfer has an optional parameter to pass the form data to the new page. <br/>Since the release version, this no longer works, because the Viewstate now has more security by default (The EnableViewStateMac defaults to true), so the new page isn’t able to access the form data. You can still access the values of the original page in the new page, by requesting the original handler: <br/><br/><br/>Page originalPage = (Page)Context.Handler;<br/><br/>TextBox textBox1 = (TextBox)originalPage.FindControl("textBox1"); ]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Sun, 23 Apr 2006 13:41:31 -0700</dc:date>
</item>
<item>
<title>[ASP.NET] printing property information</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=12</link>
<description><![CDATA[// 아래 코드의 결과물은 링크 참조<br/><br/>using System.Reflection; // must have for &#039;PropertyInfo[]&#039;<br/><br/>public class WebForm1 : System.Web.UI.Page<br/>&nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private void Page_Load(object sender, System.EventArgs e)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Context);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Response);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Request);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Session);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Server);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteProperties(Application);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void WriteProperties(object intrinsic)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type t = intrinsic.GetType();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PropertyInfo[] info = t.GetProperties();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;table border=1 style=&#039;font-size:12;font-family:tahoma;&#039; cellpadding=0 cellspacing=0&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;tr style=&#039;background-color:black;color:white;font-weight:bold;&#039;&gt;&lt;td colspan=4&gt;" + t.ToString() + "&lt;/td&gt;&lt;/tr&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;tr style=&#039;background-color:black;color:white;font-weight:bold;&#039;&gt;&lt;td&gt;Property&lt;/td&gt;&lt;td&gt;Type&lt;/td&gt;&lt;td&gt;Get/Set&lt;/td&gt;&lt;td&gt;Value&lt;/td&gt;&lt;/tr&gt;");<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt; info.Length; i++)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;tr&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;" + info[i].Name + "&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;" + info[i].PropertyType + "&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(!info[i].CanWrite)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;get&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;get/set&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object obj= info[i].GetValue(intrinsic, BindingFlags.GetProperty, null, null, null);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (obj == null)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt; &lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;" + obj + "&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;td style=&#039;background-color:white&#039;&gt;error&lt;/td&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;/tr&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;/table&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Response.Write("&lt;p&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp;  }]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Mon, 03 Apr 2006 10:23:21 -0700</dc:date>
</item>
<item>
<title>[Console] Simple Read and Write XML in C#</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=11</link>
<description><![CDATA[using System;<br/>using System.IO;<br/>using System.Xml;<br/>using System.Xml.XPath;<br/><br/>namespace xmlConsoleTest<br/>{<br/>&nbsp; &nbsp; &nbsp; &nbsp; /// &lt;summary&gt;<br/>&nbsp; &nbsp; &nbsp; &nbsp; /// Summary description for Class1.<br/>&nbsp; &nbsp; &nbsp; &nbsp; /// &lt;/summary&gt;<br/>&nbsp; &nbsp; &nbsp; &nbsp; class Class1<br/>&nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /// &lt;summary&gt;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /// The main entry point for the application.<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /// &lt;/summary&gt;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [STAThread]<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public static void Main()<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /*<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // for read and write - use ReadandWrite(..) method<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XmlTextReader rdr = new XmlTextReader(@"c:testemployees.xml");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReadandWrite(rdr);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /*<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // just to write<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XmlTextWriter writer = null;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer = new XmlTextWriter(Console.Out);<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // for easy reading, take 4 spaces<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.Formatting = Formatting.Indented;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.Indentation = 4;<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("book");<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("title");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteString("About C#");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("author");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("name");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteString("David");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("age");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteString("26");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteStartElement("price");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteString("50.00");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.WriteEndElement();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writer.Close();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XPathDocument doc = new XPathDocument("c:testemployees.xml");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XPathNodeIterator iterator = nav.Select("/bookstore/book[2]");<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (iterator.MoveNext())<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(iterator.Current.Name + ": " + iterator.Current.Value);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (Exception ex)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(ex.Message);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public static void ReadandWrite(XmlReader rdr)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (rdr.Read())<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch (rdr.NodeType)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.Element:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("&lt;" + rdr.Name);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (rdr.MoveToNextAttribute())<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write(" " + rdr.Name + "=&#039;" + rdr.Value + "&#039;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("&gt;");<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(rdr.IsEmptyElement == true)<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("#empty element");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("#begin element");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.Text:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write(rdr.Value);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("#Text");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.CDATA:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write(rdr.Value);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.ProcessingInstruction:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("&lt;?" + rdr.Name + " " + rdr.Value + "?&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.Comment:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("&lt;!--" + rdr.Value + "--&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.Document:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("&lt;?xml version=&#039;1.0&#039;?&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.Whitespace:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write(rdr.Value);<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case XmlNodeType.EndElement:<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("&lt;/" + rdr.Name + "&gt;");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.Write("#End Element");<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; &nbsp; &nbsp; }<br/>}]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Mon, 03 Apr 2006 10:19:45 -0700</dc:date>
</item>
<item>
<title>[General] Abstract Class in C#</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=10</link>
<description><![CDATA[C# Programmer's Reference   

abstract
The abstract modifier can be used with classes, methods, properties, indexers, and events.

Use the abstract modifier in a class declaration to indicate that a class is intended only to be a base class of other classes.

Abstract classes have the following features: 

An abstract class cannot be instantiated. 
An abstract class may contain abstract methods and accessors. 
It is not possible to modify an abstract class with the sealed modifier, which means that the class cannot be inherited. 
A non-abstract class derived from an abstract class must include actual implementations of all inherited abstract methods and accessors. 
Use the abstract modifier in a method or property declaration to indicate that the method or property does not contain implementation.

Abstract methods have the following features: 

An abstract method is implicitly a virtual method. 
Abstract method declarations are only permitted in abstract classes. 
Because an abstract method declaration provides no actual implementation, there is no method body; the method declaration simply ends with a semicolon and there are no braces ({ }) following the signature. For example: 
public abstract void MyMethod();
The implementation is provided by an overriding method, which is a member of a non-abstract class. 
It is an error to use the static or virtual modifiers in an abstract method declaration. 
Abstract properties behave like abstract methods, except for the differences in declaration and invocation syntax. 

It is an error to use the abstract modifier on a static property. 
An abstract inherited property can be overridden in a derived class by including a property declaration that uses the override modifier. 
An abstract class must provide implementation for all interface members. 

An abstract class that implements an interface might map the interface methods onto abstract methods. For example:

interface I 
{
   void M();
}
abstract class C: I 
{
   public abstract void M();
}
For more information, see 10.1.1.1 Abstract classes and 10.5.6 Abstract methods.

Example
In this example, the class MyDerivedC is derived from an abstract class MyBaseC. The abstract class contains an abstract method, MyMethod(), and two abstract properties, GetX() and GetY().

// abstract_keyword.cs
// Abstract Classes
using System;
abstract class MyBaseC   // Abstract class
{
   protected int x = 100; 
   protected int y = 150;
   public abstract void MyMethod();   // Abstract method

   public abstract int GetX   // Abstract property
   {
      get;
   }

   public abstract int GetY   // Abstract property
   {
      get;
   }
}

class MyDerivedC: MyBaseC
{
   public override void MyMethod() 
   {
      x++;
      y++;   
   }   

   public override int GetX   // overriding property
   {
      get 
      {
         return x+10;
      }
   }

   public override int GetY   // overriding property
   {
      get
      {
         return y+10;
      }
   }

   public static void Main() 
   {
      MyDerivedC mC = new MyDerivedC();
      mC.MyMethod();
      Console.WriteLine("x = {0}, y = {1}", mC.GetX, mC.GetY);    
   }
}
Output
x = 111, y = 161
In the preceding example, if you attempt to instantiate the abstract class by using a statement like this:

MyBaseC mC1 = new MyBaseC();   // Error
you will get the following error message:

Cannot create an instance of the abstract class 'MyBaseC'.
]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Mon, 03 Apr 2006 07:46:18 -0700</dc:date>
</item>
<item>
<title>[General] Use of Garbage Collector</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=9</link>
<description><![CDATA[대체로 GC는 프로그램이 끝날때 자동 실행되지만, 강제로 프로그램의 중간에 실행시키고 싶을때는 <br/>System.GC.Collect();<br/>System.GC.WaitForPendingFinalizers();<br/>위의 두가지를 함께 실행시킨다.<br/><br/><br/>class Class1<br/>{<br/>&nbsp; &nbsp; &nbsp; &nbsp; static void Main(string[] args)<br/>&nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SourceFile src = new SourceFile();<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; src = null;<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.GC.Collect();<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.GC.WaitForPendingFinalizers();<br/><br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("hello");<br/>&nbsp; &nbsp; &nbsp; &nbsp; }<br/>}<br/><br/>public class SourceFile<br/>{<br/>&nbsp; &nbsp; &nbsp; &nbsp; ~SourceFile()<br/>&nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("destructor");<br/>&nbsp; &nbsp; &nbsp; &nbsp; }<br/>}<br/><br/>Output with GC forced :<br/>destructor<br/>hello<br/><br/>Output without GC forced :<br/>hello<br/>destructor]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Tue, 14 Mar 2006 07:40:49 -0700</dc:date>
</item>
<item>
<title>[General] Class and Struct in C#</title>
<link>http://www.bmlee.com/bbs/board.php?bo_table=study&amp;wr_id=8</link>
<description><![CDATA[- Struct (Class)<br/>1. value type (reference type)<br/>2. can&#039;t initialize value (able to initialize value)<br/>3. no default constructor (default constructor)<br/>4. and yet, constructor is needed in Struct, use overloading<br/><br/>&nbsp; &nbsp; struct StructData<br/>&nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; public int a;<br/>&nbsp; &nbsp; &nbsp; &nbsp; public int b;<br/>&nbsp; &nbsp; &nbsp; &nbsp; public StructData(int a, int b)<br/>&nbsp; &nbsp; &nbsp; &nbsp; {<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  this.a = a;<br/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  this.b = b;<br/>&nbsp; &nbsp; &nbsp; &nbsp; }<br/>&nbsp; &nbsp; }<br/>&nbsp; &nbsp; StructData sd = new StructData(2, 3);<br/><br/><br/>- In Class, if you want creating object is to be blocked, use private constructor.<br/>Public Math<br/>{<br/>&nbsp; &nbsp; Public static double Cos(double x){...}<br/>&nbsp; &nbsp; Private Math() {...}<br/>}<br/><br/><br/>- Main() 보다 Static Constructor가 먼저 실행됨.<br/>그중에서도 static variable -&gt; static constructor]]></description>
<dc:creator>평상심</dc:creator>
<dc:date>Sun, 12 Mar 2006 08:15:38 -0700</dc:date>
</item>
</channel>
</rss>
