블로그 이미지
다비도프

만나고, 고백하고, 가슴 떨리고, 설레이고, 웃고, 사랑하고, 키스하고, 함께하고..

Rss feed Tistory
STUDY/DAAB 2007. 4. 26. 12:15

[Study] DAAB(Data Access Application Block) in Enterprise Library 2.0 - (2)

[출처 : http://www.gosu.net/GosuWeb/Article-detail.aspx?ArticleCode=1159]

[DAAB 사용법1(사용을 위한 준비 작업)]

Enterprise Library 포함된 DAAB 이전의 DAAB에서는 static 메서드를 사용해서 액세스하였다. Enterprise Library 포함된 DAAB [Plugin] 패턴을 사용한다. 플러그인은 구현 객체에 대한 의존성 정보를 설정 파일에 담아 실시간으로 관리함으로써, 어플리케이션을 구성하는 각각의 컴포넌트들이 구체적인 구현 클래스를 모르고도 상호작용 있도록 한다.

DAAB 사용하는 단계는 다음과 같다.

가장 먼저 DAAB 사용할 Data ProviderDB 연결 문자열 등의 정보를 web.config 등의 구성 정보 파일에 설정한다.

구성 정보를 구성 파일에 저장하기 위해서는 되도록이면 프레임워크에서 제공되고 있는Configuration Console 이용한다.

물론 구성 파일에 이러한 정보를 저장할 필요없이 사용할 수도 있다.


[Configuration Console 이용한 구성 정보 설정]

아래 그림은 Configuration Colsole 실행시킨 화면이다.

화면에서 New Application 선택한다.

 

 

어플리케이션을 생성한 뒤에 Data Access Application Block 선택한다.

그런 다음 Default databaseInstance 설정한다. Default databaseInstance 인스턴스 이름없이 DAAB DatabaseFactory.CreateDatabase 호출했을 사용되는 인스턴스 정보를 담게 된다.

DAAB DatabaseFactory.CreateDatabase 메서드를 사용해서 Database 생성할 인자로 인스턴스 이름을 주게 된다.

Configuration Tool 이용해서 Default database Instance, Named Instance( 그림에서는 Northwind, Orders) 구성할 있고 인스턴스 별로 별도의 DB 연결 문자열, ADO.NET Data Provider 설정할 있다.

구성 정보만으로 Application Code  수정없이 DB 연결과 관련된 정보를 변경할 있음으로해서 DataBase 독립적인 코딩이 가능하다.

아래 그림은 Default database Instance, Named Instance(Northwind, Orders) 설정한 예이다.

 

왼쪽 트리에서 Data Access Application Block 선택하면 오른쪽 윈도우에서 DefaultDatabase Name에서 Default Database Instance 이름을 설정할 있다.

그럼 각각의 인스턴스에 대한 구체적인 설정을 살펴보겠다.

Default Database Instance 경우(다른 Named Instance 같다)  왼쪽에서 해당 인스턴스를 선택하면 오른쪽 창에서 해당 인스턴스의 Data Provider 선택할 있으며 해당 DB DB 연결 문자열을 구성하는 각각의 값들을 설정할 있다. 경우 해당 값이 없으면 새로이 추가하면 된다.

User ID Password 디폴트로 없는 상태이므로 새롭게 추가하여 해당 값을 설정하면 된다.

설정이 끝나면 Save Application 메뉴를 통해 해당 구성 정보를 저장할 구성 파일을 지정한다.

 

 

아래 그림은 3개의 인스턴스를 설정한 Configuration Tool 모습과 실제 구성 파일에 저장된 내용을 보여주고 있다.

 

<configuration>

  <configSections>

    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />

    <section name="oracleConnectionSettings" type="Microsoft.Practices.EnterpriseLibrary.Data.Oracle.Configuration.OracleConnectionSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />

  </configSections>

  <dataConfiguration defaultDatabase="Northwind" />

  <oracleConnectionSettings>

    <add name="Orders">

      <packages>

        <add prefix="OP2" name="Oracle Package2" />

        <add prefix="OP1" name="Oracle Package1" />

      </packages>

    </add>

  </oracleConnectionSettings>

  <connectionStrings>

    <add name="Default Database Instance" connectionString="Database=Database;Server=(local)\SQLEXPRESS;Integrated Security=SSPI;"

      providerName="System.Data.SqlClient"/>

    <add name="Orders" connectionString="Data Source=Northwind;Server=(local);User ID=scott;Password=tiger;"

      providerName="System.Data.OracleClient" />

    <add name="Northwind" connectionString="Database=Northwind;Server=abc;User ID=sa;Password=password;"

      providerName="System.Data.SqlClient"/>

  </connectionStrings>

</configuration>

 

위의 구성 정보 OracleConnectionSettings내에 있는 Package 부분이 필요한 이유는 다음과 같다. 오라클의 Stored Procedure 패키지내에 그룹핑되어 있는 경우 이를 호출하기 위해서는 Stored Procedure 이름 앞에 패키지 이름을 붙여 주어야 한다.

그러나 이렇게 경우 개발되는 코드들은 오라클이라고 하는DB 종속적이게 된다. DAAB 이러한 패키지 이름과 Prefix 위와 같이 구성 정보에 관리하여 개발자가 작성하는 코드는 이러한 패키지명에 신경쓰지 않고 코딩할 있게 함으로써 결과적으로 개발되는 코드가 DB 독립적이게 한다.

위와 같이 패키지명과 Prefix 구성 정보에 담게 되면DAAB 알아서 해당 Stored Procedure 호출할 내부적으로 이를 처리해주므로 개발자는 다른DB 같은 방식으로 Stored Procedure 호출하면 된다. 개발자는 단지 위의 구성 정보 매핑에 있는데로 해당Stored Procedure 이름을 해당 Prefix 시작하게 하면 된다.

위의 구성 정보에서 prefix “*” 사용하게 되면  모든 Stored Procedure 호출시에 관련된 패키지명이 붙게 된다.

이러한 패키지와 Prefix와의 매핑은 오라클 DB에만 한정되는 얘기이다.

 

Configuration Tool 만들어주는 구성 정보에 대한 자세한 설명은 Enterprise Library 설명서내 Data Access Application Block 부분 Source Schema for the Data Access Application Block 부분을 참고하기 바란다.

 

이와 같이 DAAB 사용하기 위한 구성 정보를 일일이 구성 파일을 열어 설정할 필요없이 GUI 화면을 통해 쉽게 설정할 있게 하는Configuration Tool 제공하고 있다. 주의할 것은 각각의 Key/Value 값들은 유효성 검사를 수행하지는 않는다. 단지 키와 값이 같이 존재하는지 여부만 체크한다는 사실을 주의해야 한다.

결국 사용자의 책임하에 /값을 사용해서 구성 정보를 설정해야 한다.

 

관련DLL 참조 추가 Using Namespace 설정

DAAB 사용하기 위해서는 관련DLL 우선 참조 추가해야 한다.

 

 

그림처럼 Microsoft.Practices.EnterpriseLibrary.Data.dll, Microsoft.Practices.EnterpriseLibrary.Common.dll, Microsoft.Practices.EnterpriseLibrary.ObjectBuilder.dll 참조 추가한다.

 

그리고 아래와 같이 개발할 코드이 상위에 using 문을 추가한다.(C# 경우)

using Microsoft.Practices.EnterpriseLibrary.Data;

using System.Data;

,
STUDY/DAAB 2007. 4. 26. 12:09

[Study] DAAB(Data Access Application Block) in Enterprise Library 2.0 - (1)

[출처 : http://www.gosu.net/GosuWeb/Article-detail.aspx?ArticleCode=1158]

개요

DAAB(Data Access Application Block) in Enterprise Library for .NET 2.0DAC(Data Access Component) 레이어에서의 반복적인 ADO.NET 코딩량을 감소시켜주며 DB 커넥션 관리와 같은 사용자가 실수하기 쉬운 부분을 관리해주는 DAAB(Data Access Application Block) Enterprise Library 통합된 버전이다. 또한 Enterprise Library 1.x 있던 DAAB ADO.NET 2.0 변화된 기능에 맞게 수정한 것이DAAB(Data Access Application Block)   in Enterprise Library for .NET 2.0이다.

DAAB(Data Access Application Block)  in Enterprise Library for .NET 2.0 .NET Framework 2.0 기반의 프로젝트라면 어플리케이션, 윈도우 어플리케이션, 스마트 클라이언트 어플리케이션에 관계없이 사용 가능하다.

DAAB(Data Access Application Block)  in Enterprise Library for .NET 2.0 사용을 통해 DAC(Data Access Component) 레이어에서의 반복적인 ADO.NET 코딩량을 감소시킬 있으며 DB 커넥션 관리와 같은 사용자가 실수하기 쉬운 부분의 실수를 최소화할 있다.

DAAB(Data Access Application Block)  in Enterprise Library for .NET 2.0 .NET Framework 2.0 기반의 프로젝트에서 DAC(Data Access Component) 레이어의 Data Framework 역할을 하게 된다.


아티클은 엔터프라이즈 라이브러리 데이터 액세스 응용 프로그램 블록의 개요를 제공한다. 이것은 .NET기반 응용 프로그램들의 일반적인 데이터 액세스 기능 개발을 단순화시켜주는 재사용 가능하고 확장 가능한 소스 코드 기반의 지침이다.

DAAB 소개

엔터프라이즈 라이브러리 데이터 액세스 응용 프로그램 블록, 버전2.0 일상적인 데이터 액세스 기능을 구현하는 개발 작업들을 단순화 했다. 응용 프로그램들은 응용 프로그램 블록을 화면에 표시하기 위해 데이터를 읽고 , 응용 프로그램 계층 데이터 전달을 위해 데이터 가져오고 , 그리고 변경된 데이터를 데이터베이스에 다시 보내는 것과 같은 다양한 상황들 안에서 사용할 있다. 응용 프로그램 블록은 저장프로시저와 인라인SQL 모두에 대한 지원을 포함하고 있으며, 연결들을 관리하는 것이나 파라미터들을 만들고 캐싱하는 것과 같은 일상적인 작업들은 응용 프로그램 블록의 메소드 안에 내장되어 있다. 다시 말해, 데이터 액세스 응용 프로그램 블록은 ADO.NET에서 가장 자주 사용되는 기능들에 대한 액세스를 제공한다.

응용 프로그램 블록은 Microsoft SQL Server, Oracle, 그리고 DB2 포함한 다수의 데이터베이스 서버들에 동일한 코드를 사용할 있게 해줌으로써 이식 가능한 응용 프로그램 코드 개발을 용이하게 한다. 이것은 공통된 인터페이스를 정의하고 데이터 액세스 메소드들을 위한 대부분의 구현을 제공하는 추상화된 기반 클래스를 사용함으로써 가능하다. 예를 들어, SQL Server 종류의 데이터베이스를 위해 작성된 응용 프로그램들은 Oracle 같이 다른 종류의 데이터베이스를 위해 작성된 응용 프로그램과 같아 보이게 된다. 데이터 액세스 응용 프로그램 블록을 사용하고 가이드의 지침들을 따른다면, 코드들은 대부분 이식 가능한 상태로 유지된다.


데이터 액세스 응용 프로그램 블록은 다음과 같은 기능을 갖고 있다.

  • 표준화된 작업들을 수행하는 반복적인 코드를 작성할 필요를 줄인다
  • 응용 프로그램 안이나 기업 내에서 일관된 데이터 액세스 관행들을 유지하는데 도움을 준다.
  • 물리적인 데이터베이스 대상을 변경하는데 따르는 어려움들을 줄인다.
  • 개발자들이 다른 종류의 데이터베이스들에 대해 다른 프로그래밍 모델을 학습해야 하는 부담을 줄인다.
  • 다른 종류의 데이터베이스에 응용 프로그램을 이식할 , 작성해야 하는 코드의 양을 줄인다.

데이터 액세스 응용 프로그램 블록은 가장 일상적인 데이터 액세스 작업들에 대한 구현을 제공함으로써 기능들을 제공한다. 개발자들은 단지 다음과 같이 하면 된다.

  •  데이터베이스 개체를 생성한다.
  • 만약 필요한 경우, 명령에 대한 파라미터들을 제공한다.
  • 적합한 메소드를 호출한다.

이들 메소드들은 성능을 위해 최적화 되어 있다. 그것들은 이식 가능하다. 데이터 액세스 응용 프로그램 블록은 SQL Server, DB2, 그리고 Oracle 데이터베이스들에 투명하게 동작한다.


아래 그림은 DAAB 클래스를 나타내고 있다.

 

 

변화된내용(Enterprise Library 1.x -> 2.0)

DAAB(Data Access Application Block)  in Enterprise Library for .NET 2.0 Enterprise Library for .NET 1.x 비해 변화된 내용은 다음과 같다.

.NET Framework 2.0 새로이 추가된 System.Data.Common 네임스페이스로 동일한 역할을 하는DBCommandWrapper 없어졌다.

SQL Server 오라클 데이터 베이스 이외의 DB 지원하기 위해GenericDatabase 추가되었다.

,
STUDY/SQL Cache Dependency 2007. 4. 25. 18:36

[Study] ASP.NET Caching: SQL Cache Dependency With SQL Server 2000

Introducing Cache Dependencies:

As time passes, the data source may change in response to other actions. However, if your code uses caching, you may remain unaware of the changes and continue using out-of-date information from the cache. To help mitigate this problem, ASP.NET supports cache dependencies. Cache dependencies allow you to make a cached item dependent on another resource so that when that resource changes the cached item is removed automatically. ASP.NET includes three types of dependencies:

  • Dependencies on other cache items.
  • Dependencies on files or folders.
  • Dependencies on a database query.

Introducing SQL Cache Notifications:

SQL cache dependencies are one of the most wonderful new features in ASP.NET 2.0, the ability to automatically invalidate a cached data object (such as a DataSet or Custom Data Type) when the related data is modified in the database. This feature is supported in both SQL Server 2005 and in SQL Server 2000, although the underlying plumbing is quite different.

Cache Notifications in SQL Server 2000:

Before you can use SQL Server cache invalidation, you need to enable notifications for the database. This task is performed with the aspnet_regsql.exe command-line utility, which is located in the c:\[WinDir]\Microsoft.NET\Framework\[Version] directory. To enable notifications, you need to use the -ed command-line switch. You also need to identify the server (use -E for a trusted connection and -S to choose a server other than the current computer) and the database (use -d). Here's an example that enables notifications for the Northwind database on the current server:

aspnet_regsql -ed -E -d Northwind
After executing this command, a new table named SqlCacheTablesForChangeNotification is added to the database Northwind. The SqlCacheTablesForChangeNotification table has three columns: tableName, notificationCreated, and changeId. This table is used to track changes. Essentially, when a change takes place, a record is written into this table. The SQL Server polling queries this table. Also a set of stored procedures is added to the database as well. See the following table.

Procedure Name Description
AspNet_SqlCacheRegisterTableStoredProcedure Sets a table up to support notifications. This process works by adding a notification trigger to the table, which will fire when any row is inserted, deleted, or updated.
AspNet_SqlCacheUnRegisterTableStoredProcedure Takes a registered table and removes the notification trigger so that notifications won't be generated.
AspNet_SqlCacheUpdateChangeIdStoredProcedure The notification trigger calls this stored procedure to update the AspNet_SqlCacheTablesForChangeNotification table, thereby indicating that the table has changed.
AspNet_SqlCacheQueryRegisteredTablesStoredProcedure Extracts just the table names fromthe AspNet_SqlCacheTablesForChangeNotification table. Used to get a quick look at all the registered tables.
AspNet_SqlCachePollingStoredProcedure Gets the list of changes from the AspNet_SqlCacheTablesForChangeNotification table. Used to perform the polling.

After this, need to enable notification support for each individual table. You can do this manually using the AspNet_SqlCacheRegisterTableStoredProcedure, to that, open your query analyzer and select your Database you've enabled for SQL Cache Notification for example Northwind database and write the following command:

exec AspNet_SqlCacheRegisterTableStoredProcedure 'TableName'

Or you can use aspnet_regsql, using the -et parameter to enable a able for sql cache dependency notifications and the -t parameter to name the table. Here's an example that enables notifications for the Employees table:

aspnet_regsql -et -E -d Northwind -t Products

Both options generates the notification trigger for the Products table as the following:

CREATE TRIGGER dbo.[Products_AspNet_SqlCacheNotification_Trigger] ON
[Products]
FOR INSERT, UPDATE, DELETE
AS
BEGIN

SET NOCOUNT ON
EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'Products'
END

So any record is inserted, deleted or updated in Products table will update ChangeId field in AspNet_SqlCacheTablesForChangeNotification table.

How Notificaions Works:

The AspNet_SqlCacheTablesForChangeNotification contains a single record for every table you're monitoring. When you make a change in the table (such as inserting ,deleting or updating a record), the changeId column is incremented by 1 -see AspNet_SqlCacheUpdateChangeIdStoredProcedure procedure-. ASP.NET queries this table repeatedly and keeps track of the most recent changeId values for every table. When this value changes in a subsequent read, ASP.NET knows that the table has changed.

In this scenario, Any change to the table is deemed to invalidate any query for that table. In other words, if you use this query:

SELECT * FROM Products WHERE CategoryID=1

The caching still works in the same way. That means if any product record is touched, even if the product resides in another category (and therefore isn't one of the cached records), the notification is still sent and the cached item is considered invalid. Also keep in mind it doesn't make sense to cache tables that change frequently.

Enable ASP.Net Polling:

To enable ASP.NET polling , you need to use the <sqlCacheDepency> element in the web.config file. Set the enabled attribute to true to turn it on, and set the pollTime attribute to the number of milliseconds between each poll. (The higher the poll time, the longer the potential delay before a change is detected.) You also need to supply the connection string information.

Creating the Cache Dependency:

Now that we've seen how to set up a database to support SQL Server notifications, the only remaining detail is the code, which is quite straightforward. We can use our cache dependency with programmatic data caching, a data source control, and output caching.

For programmatic data caching, we need to create a new SqlCacheDependency and supply that to the Cache.Insert() method. In the SqlCacheDependency constructor, you supply two strings. The first is the name of the database you defined in the element in the section of the web.config file e.g: Northwind. The second is the name of the linked table e.g: Products.

Example:

private static void CacheProductsList(List<NWProductItem> products)
{

SqlCacheDependency sqlDependency = new SqlCacheDependency("Northwind", "Products");
HttpContext.Current.Cache.Insert("ProductsList", products, sqlDependency, DateTime.Now.AddDays(1), Cache.NoSlidingExpiration);

}

private static List<NWProductItem> GetCachedProductList()
{

return HttpContext.Current.Cache["ProductsList"] as List<NWProductItem>;

}

NWProductItem is business class, and here we are trying to cache a list of NWProductItem instead of DataSet or DataTable.

The following method is used by an ObjectDataSource Control to retrieve List of Products

public static List<NWProductItem> GetProductsList(int catId, string sortBy)
{

//Try to Get Products List from the Cache
List<NWProductItem> products = GetCachedProductList();
if (products == null)
{

//Products List not in the cache, so we need to query the Database by using a Data Layer
NWProductsDB db = new NWProductsDB(_connectionString);
DbDataReader reader = null;
products = new List<NWProductItem>(80);

if (catId > 0)
{

//Return Product List from the Data Layer
reader = db.GetProductsList(catId);

}
else
{

//Return Product List from the Data Layer
reader = db.GetProductsList();

}
//Create List of Products -List if NWProductItem-
products = BuildProductsList(reader);
reader.Close();

//Add entry to products list in the Cache
CacheProductsList(products);

}
products.Sort(new NWProductItemComparer(sortBy));

if (sortBy.Contains("DESC")) products.Reverse();
return products;

}

To perform the same trick with output caching, you simply need to set the SqlDependency property with the database dependency name and the table name, separated by a colon:

<%@ OutputCache Duration="600" SqlDependency="Northwind:Products" VaryByParam="none" %>

The same technique works with the SqlDataSource and ObjectDataSource controls:

<asp:SqlDataSource EnableCaching="True" SqlCacheDependency="Northwind:Products" ... />

Important Note:
ObjectDataSource doesn't support built in caching for Custom types such as the one in our example. It only support this feature for DataSets and DataTables.

To test this feature, download the attached demo. It contains an editable GridView. Set a break point at the GetProductList method and run in debug mode. Update any record and notice the changes. Also you can edit the solution and remove the cache dependency and note the deference after update.

Also you can remove the SqlDependency from the output cache in the OutputCaching.aspx page, and notice that whatever update you made to the data source, the page still retrieves the old version of data.

ASP.NET Caching: SQL Cache Dependency With SQL Server 2000

SQL cache dependencies are one of the most wonderful new features in ASP.NET 2.0, the ability to automatically invalidate a cached data object (such as a DataSet or Custom Data Type) when the related data is modified in the database. This feature is supported in both SQL Server 2005 and in SQL Server 2000, although the underlying plumbing is quite different.



[출처 : http://www.c-sharpcorner.com/UploadFile/mosessaur/sqlcachedependency01292006135138PM/sqlcachedependency.aspx?ArticleID=3caa7d32-dce0-44dc-8769-77f8448e76bc]
,
STUDY/SQL Cache Dependency 2007. 4. 25. 17:07

[Study] aspnet_regsql

SQL 서버에 ASP.NET 기능을 설치 및 제거하는 관리 유틸리티입니다.
Copyright (C) Microsoft Corporation. All rights reserved.

-- 일반 옵션 --
-? 이 도움말 텍스트를 표시합니다.
-W 마법사 모드입니다. 다른 매개 변수를 지정하지 않을 경우 기본값으로 사용됩니다.
-- SQL 연결 옵션 --
-S [서버] 사용할 SQL Server 인스턴스(SQL Server 7.0 이상)입니다.
-U [로그인 ID] 인증하는 데 사용할 SQL Server 사용자 이름입니다. -P 옵션을 사용해야 합니다.
-P [암호] 인증하는 데 사용할 SQL Server 암호입니다. -U 옵션을 사용해야 합니다.
-E 현재 Windows 자격 증명을 사용하여 인증합니다.
-C [연결문자열] 연결 문자열입니다. 사용자 이름, 암호 및 서버 이름을 지정하는 대신 SQL Server 연결 문자열을 지정할 수 있습니다. 별도로 지정하지 않는 한 이 문자열에 데이터베이스 이름을 사용하면 안 됩니다.
-sqlexportonly [파일이름] 지정한 기능을 추가하거나 제거하는 SQL 스크립트 파일을 생성하고 실제 작업은 수행하지 않습니다. -A, -R, -ssadd 및 -ssremove 옵션을 사용할 수 있습니다.
,
STUDY/SQL Cache Dependency 2007. 4. 25. 16:44

[Study] Wicked Code : Supporting Database Cache Dependencies in ASP.NET

[출처 : http://msdn.microsoft.com/msdnmag/issues/03/04/wickedcode/]
Developers love the ASP.NET application cache. One reason they love it is that ASP.NET lets them create dependencies between items placed in the cache and files in the file system. If a file targeted by a dependency changes, ASP.NET automatically removes dependent items from the cache. Combined with cache removal callbacks—notifications broadcast to interested parties when cached items are removed—cache dependencies are a boon to developers seeking to maximize performance by minimizing time-consuming file accesses because they permit file data to be cached without fear of it becoming stale.

As awesome as cache dependencies are, in ASP.NET version 1.0 they lack one critical feature that, if present, would qualify them as a developer's dream come true: support for database entities. In real life, most Web apps fetch data from databases, not files. But while ASP.NET is perfectly willing to link cached items to files, it is incapable of linking cached items to database entities. In other words, you can read the contents of a file into a DataSet, cache the DataSet, and have the DataSet automatically removed from the cache if the file it was initialized from changes. But you can't initialize a DataSet with a database query, cache the DataSet, and have the DataSet automatically discarded if the database changes. That's too bad because too many database accesses, like too much file I/O, is a performance killer.

The fact that ASP.NET doesn't support database dependencies doesn't mean database dependencies are impossible to achieve. This installment of Wicked Code presents a technique for extending the ASP.NET application cache to support database dependencies. It involves database triggers and extended stored procedures. Though the implementation presented here works exclusively with Microsoft® SQL Server™, the general technique is applicable to any database that supports triggers and user-defined procedures that interact with the file system.


Database Dependencies in Action

Let's begin with a demonstration. Figure 1 contains the source code for an ASP.NET page that displays randomly selected quotations from a SQL Server database named Quotes. To create the database, run the installation script shown in abbreviated form in Figure 2. The complete script is included in the downloadable zip file that accompanies this column. You can execute the script inside the SQL Server Query Analyzer or from the command line with an OSQL command.) Each time the page is fetched, Page_Load initializes a DataSet with all the records in the database's Quotations table, randomly selects a record from DataSet, and writes it to the page. Press F5 a few times and you'll see a random variety of quotations from some famous (and not-so-famous) people, as shown in Figure 3.

Figure 3 Random Quote
Figure 3 Random Quote

The page is called DumbDBQuotes.aspx for a reason. It's not very smart considering it queries the database each time it's requested. Accessing a database on every page access—especially a database hosted on a remote server—is a guaranteed way to build an application that won't scale.

The ASP.NET application cache is the solution to the problem of too many database accesses. If the DataSet were cached, it could be fetched directly from memory—that is, from the cache—thereby eliminating the redundant database accesses. It's easy enough to cache a DataSet; the application cache accepts instances of any type that derives from System.Object. In the Microsoft .NET Framework, that means instances of any managed type, including DataSet. The problem is that if you cache a DataSet and the database changes underneath it, you serve stale data to your users. You could implement a solution that requeries the database periodically, but the ideal solution is the one that requires no polling and that delivers fresh data from the data source the moment that data becomes available.

Take a look at Figure 4 and Figure 5, which contain the source code for a smarter quotes application. SmartDBQuotes.aspx doesn't retrieve quotations from the database; it gets them from the application cache. Global.asax primes the cache and refreshes it if the database changes. Here are directions for taking them for a test drive:

  1. Create a subdirectory named AspNetSql in the root directory of your Web server's C: drive. Inside AspNetSql, create a zero-byte file named Quotes.Quotations. Make sure Everyone, or at least SYSTEM and ASPNET (a special account created when ASP.NET is installed), has access to Quotes.Quotations.
  2. Copy XSP.dll, which is included in this column's downloadable code sample, into the SQL Server binn directory (for example, C:\Program Files\Microsoft SQL Server\MSSQL\Binn) or to any location on your Web server that Windows will automatically search for DLLs (for example, C:\Windows\System32).
  3. Rebuild the database using the modified script in Figure 6.
  4. Deploy Global.asax and SmartDBQuotes.aspx to a virtual directory on your Web server (for example, wwwroot).
  5. Request SmartDBQuotes.aspx in your browser. Refresh the page a few times until the quote "The use of COBOL cripples the mind; its teaching should therefore be regarded as a criminal offense" appears.
  6. Use SQL Server Enterprise Manager or the tool of your choice to modify the quotation in the Quotes database's Quotations table. Change it to read "The use of Visual Basic® enriches the mind; its teaching should therefore not be regarded as a criminal offense." Then refresh the page until the modified quotation appears. Observe that the new quotation appears, not the old one, even though the query results are now being stored in the application cache.

You just demonstrated that the ASP.NET application cache can be combined with database dependencies to produce high-volume, data-driven applications. The question is how? How was a link formed between the cached DataSet and the database, and how scalable is the solution?

Back to top

How Database Dependencies Work

On the outside, both DumbDBQuotes.aspx and SmartDBQuotes.aspx look the same, producing identical output. On the inside, they could hardly be more different. The former performs a database access every time it's requested; the latter fetches data from the application cache. Moreover, SmartDBQuotes.aspx uses a database dependency to ensure that if the database changes, the cached data changes, too. If the database doesn't change, the database is queried just once during the lifetime of the application. If the database changes, one more query updates the cache.

Figure 7 Database Dependencies
Figure 7 Database Dependencies

Figure 7 illustrates how the database dependency works. When it places the DataSet in the cache, Global.asax creates a file-system dependency between the DataSet and a file named Quotes.Quotations in the C:\AspNetSql directory. Quotes.Quotations is a zero-byte signal file—a file whose only purpose is to trigger the ASP.NET application cache-removal logic. Here's the statement in Global.asax that creates the CacheDependency object linking the DataSet to Quotes.Quotations:

new CacheDependency ("C:\\AspNetSql\\Quotes.Quotations")
Global.asax also registers its own RefreshCache method to be called when the DataSet is removed from the cache—that is, when the signal file changes:
new CacheItemRemovedCallback (RefreshCache)

RefreshCache's job is to query the database and place the resulting DataSet in the application cache. It's called once when the application starts up and again when—or if—the DataSet is removed from the cache.

That's half of the equation. The other half involves the database. The revised database installation script in Figure 6 adds an insert/update/delete trigger to the database's Quotations table:

CREATE TRIGGER DataChanged ON Quotations
FOR INSERT, UPDATE, DELETE
AS EXEC master..xsp_UpdateSignalFile 'Quotes.Quotations'
GO
The trigger fires when records are added to or deleted from the table and when records change. What does the trigger do? It calls an extended stored procedure—the SQL Server euphemism for code in a Win32® DLL—named xsp_UpdateSignalFile. The extended stored procedure, in turn, uses the Win32 CreateFile function to update Quotes.Quotations' time stamp.

The cached DataSet's lifetime is tied to Quotes.Quotations using an ordinary file-system cache dependency; updating the Quotations table causes a database trigger to fire; and the trigger calls an extended stored procedure that "updates" Quotes.Quotations, prompting ASP.NET to remove the DataSet from the application cache and call Global.asax's RefreshCache method, which then performs a brand new database query and starts the whole process all over again.

The final piece of the puzzle is the extended stored procedure. It's housed in XSP.dll, the DLL that you installed earlier. I wrote XSP.dll in unmanaged C++ using Visual C++® 6.0. Its source code appears in Figure 8. The path to the signal file—C:\AspNetSql—is hardcoded into the DLL, but you can change that if you'd like and make it an input parameter just like the file name.

Extended stored procedures must be installed before they're used. The following statements in the SQL installation script that you executed install xsp_UpdateSignalFile in the master database and grant execute permission to all comers:

USE master
EXEC sp_addextendedproc 'xsp_UpdateSignalFile', 'XSP.dll'
GRANT EXECUTE ON xsp_UpdateSignalFile TO PUBLIC
GO
Why write a custom extended stored procedure to update a file's time stamp when a built-in extended stored procedure such as xp_cmdshell could be used instead? The reason is security—xp_cmdshell can be used for all sorts of malicious purposes, while xsp_UpdateSignalFile cannot. Because xsp_UpdateSignalFile does little more than call the Windows CreateFile function, it is also more efficient than xp_cmdshell.
Back to top

Server Farms

SmartDBQuotes.aspx and friends work great if the Web server and the database server live on the same machine, but what if the database is installed on a different machine? And what about Web farms? Would a change notification mechanism based on database triggers, extended stored procedures, and file-system dependencies be compatible with multiserver installations?

You bet. Under the hood, ASP.NET cache dependencies that are based on the file system rely on Win32 file change notifications. And Win32 file change notifications support Universal Naming Convention (UNC) path names. To take advantage of database cache dependencies on Web farms, let the signal file reside on the database server, as shown in Figure 9. Then pass CacheDependency's constructor a UNC path name specifying the signal file's network address:

new CacheDependency 
(@"\\ServerName\AspNetSql\Quotes.Quotations"),
Figure 9 Signal File on Database Server
Figure 9 Signal File on Database Server

The greatest obstacle to creating dependencies that target remote files is security. By default, the ASP.NET worker process runs as ASPNET when paired with Microsoft Internet Information Services (IIS) 5.0 and when configured to run in compatibility mode under IIS 6.0. ASPNET is a local account that can't authenticate on remote machines. Without configuration changes, attempting to create a cache dependency with a UNC path name produces an access denied error—even if you give Everyone access to the remote share.

Several solutions exist. One is to configure ASP.NET to use a domain account that can be authenticated on the database server. That change is easy enough to accomplish: you simply specify the account's user name and password in the <processModel> section of each Web server's Machine.config. Many companies, however, have security policies that prevent passwords from being stored in plaintext configuration files. If that's true of your company, but you'd still like to run ASP.NET using a domain account, you can either upgrade to version 1.1 of the .NET Framework (which allows worker process credentials to be encrypted and stored securely in the registry) or download a hotfix for version 1.0 that does the same. You'll find information about the hotfix at Stronger Credentials for processModel, identity, and sessionState.

A variation on this technique involves setting up identical local accounts (using the same user name and password) on both machines and configuring ASP.NET to run as that identical local account on the Web server.

Another solution to the problem of authenticating on a back-end database server containing a signal file is to upgrade to Windows Server 2003. The latest addition to the Windows Server family comes with IIS 6.0, which allows the ASP.NET worker process to run using the identity of Network Service. Unlike ASPNET, Network Service can perform authentication on remote machines. Or you could pull an old trick out of the ASP playbook and access the database through a COM+ component running on the Web server and configure the component to run as a principal that has network credentials.

However you choose to make the remote signal file accessible to your ASP.NET app, the bottom line is that combining database cache dependencies with UNC path names delivers a scalable solution that works equally well for Web farms and single-server installations. That's good news for developers who are using ASP.NET to build high-volume, data-driven applications—and good news for users as well.

,
STUDY/SQL Cache Dependency 2007. 4. 25. 15:58

[Study] Using the SQL Server Cache Dependency

1. SQL Cache 종속성을 사용하도록 데이터베이스 설정
aspnet_regsql -S localhost -U sa -P password -d testDB -ed

2. SQL Cache 종속성을 테이블에 활성화시킨다.
aspnet_regsql -S localhost -U sa -P password -d testDB -t tblMember -et

3. SQL Cache 종속성이 설정된 테이블 목록을 조회한다.
aspnet_regsql –S localhost –U sa –P password –d testDB -lt

4. SQL Server Cache Dependency 설정 해제 명령어

1) DB 해제
aspnet_regsql -S localhost -U sa -P password -d testDB -dd

2) Table 해제
aspnet_regsql -S localhost -U sa -P password -d testDB -t tblMember -dt

5. Web.config 설정

<caching>

    <sqlCacheDependency enabled="true">

      <databases>

        <add name="Northwind" connectionStringName="ConnectionString" pollTime="500" />

      </databases>

    </sqlCacheDependency>

</caching>

è  connectionStringName web.config 설정된 ConncetionString값과 동일하게 설정함.

è  pollTime 단위 : milliseconds

G.      SQL Server Cache Dependency 페이지 적용 (aspx page)
<%
@ OutputCache Duration="3600" VaryByParam="none"
SqlDependency="Northwind:Customers" %>

Or

<%@ OutputCache Duration="3600" VaryByParam="none"
SqlDependency="Northwind:Customers;Northwind:Products" %>

è  SqlDependency = “DatabaseName:TableName”


[출처 : http://blog.naver.com/metalzang?Redirect=Log&logNo=130016491535]
,
WEB 2007. 4. 25. 15:25

[Tip] Ping 과 traceroute를 이용한 자가 네트워크 점검 방법

[Ping]
ping 은 특정 서버에 일정양의 데이터를 보내어 왕복하는 시간을 체크하여 특정 구간의 네트워크 상황을 체크하는 프로그램입니다. 마치 선박에서 바다의 깊이를 잴 때 전파를 쏘아 되돌아오는 시간을 체크하여 바다의 깊이를 예상하는 것과 같은 이치입니다. ping 에 대해 기술적으로 설명을 하면 "ICMP 프로토콜의 ECHO_REQUEST datagram을 지정한 호스트나 네트워크 게이트웨이에 보내어 ICMP ECHO_RESPONSE를 이끌어 내는 것" 을 말합니다. 일반적으로 특정 ip 로 ping을 보냈을 때 응답시간이 늦으면 양구간 사이에 트래픽이 몰리거나 속도가 느린 것이고 반응을 하지 않을때는 원격지나 중간 네트워크가 다운된 것입니다. 그러나 특정 서버에 ping을 쏘았을 때 응답하지 않는다고 해서 반드시 다운된 것은 아니며 다만 특정 서버나 중간 라우터에서 보안상의 문제로 ping 에 반응하지 않도록 설정하였을 경우도 있습니다.




[Traceroute]
웹사이트로 접속할 경우 PC에서 서버로 직접 접속이 되는 것이 아니라 중간중간에 라우터라는 장비를 거쳐 매우 복잡한 단계를 통해 접속이 되는 것입니다. ping 은 단순히 원격지에 일정량의 데이터를 보내 돌아오는 결과를 보고 양 구간 사이의 속도와 데이터의 손실 여부만을 체크하는 것이라면 traceroute 는 접속이 되는 각 경로를 체크하여 어떠한 경로를 거쳐 접속이 되고 어떠한 구간에서 얼마만큼의 속도 지연이 되는지를 확인할 수 있습니다.
그러나 traceroute 는 시간대,사용자수,내부트래픽,연결하려는 서버의 상태등 많은 원인에 의해 그 결과가 달라질수 있으니 여라차례 반복적으로 확인을 하셔야 합니다.

c:\>tracert www.mediamob.co.kr


출처 : http://kin.naver.com/db/detail.php?d1id=1&dir_id=10302&eid=Or9/Lhx9+2pGLtJ3SoTwiyNOzGIRJEte&qb=cGluZw==
,
WEB/ASP.NET With C# 2007. 4. 20. 16:20

[CodeGuru] ASP.NET 2.0 Profile: Simple User Personalization for Your Web Apps

[링크 : http://www.codeguru.com/Csharp/.NET/net_asp/controls/article.php/c10179/#more]

Most enterprise Web applications need to track user preferences across multiple visits. In ASP.NET 1.x, you need to write lots of code to create this functionality. ASP.NET 2.0 introduces a new object, named profile, that simplifies the steps involved in tracking personalization information. This article provides an introduction to the profile object and differentiates it from the session object. It also demonstrates how to define user profiles, both simple name/value pair profiles and profile groups. Finally, it explains the procedures involved in configuring profiles to work with different providers.
work with different providers.

An Overview of Profile Object

In an ASP.NET profile, information is stored in a persistent format and is associated with an individual user. The ASP.NET profile allows you to easily manage user information without having to create and maintain your own database. You can store any type of object in the profile because of its generic storage system. In addition, you also can make the same data available in a type-safe manner.

Is the Profile Object the Same as the Session Object?

At first look, the profile object might look very similar to the session object. But, there are a number of differences between the two objects. Table 1 outlines these differences.

Table 1. Differences Between the Profile and Session Objects

Characteristics Profile Session
Scope Each user has his own profile object Each user has his own session object
Strongly typed nature Profile object is strongly typed Session object is not strongly typed and requires type casting when assigning and retrieving from the session object
Persistent duration Profile values are available for the users, even between visits Session object contents are available only for the duration of the current browser session
Persistent location Profile object can be stored in a SQL Server Express database or in a SQL Server database and can be configured through the Web Site Administration tool Session object can be configured to be stored in a database, IIS in-process, or in a session state server, depending on the configuration setting
Performance Profile may have a negative impact on performance because of the chatty interface between the profile object and the persistent data store Can be configured using properties such as EnableSessionState attributes at the page level
IntelliSense Provides IntelliSense because of its strongly typed nature No support for IntelliSense

Now that you have a general understanding of the important characteristics of the profile object, take a look at an example.

Defining User Profiles

You define a user profile within the application root web.config file. You cannot create a web.config file containing a profile section in an application subfolder. This means that you can have only one profile element declaration for one Web application. The following declaration in the web.config contains a simple profile definition:

<configuration
   xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   <system.web>
      <profile>
         <properties>
           <add name="Name" type="System.String"/>
           <add name="UserCount" type="System.Int16"/>
         </properties>
      </profile>
      -----
      -----
   </system.web>
</configuration>

As you can see, the profile defines two properties: Name and UserCount. The default data type for profile properties is the System.String data type. In the above example, the Name property explicitly declares the data type to be of System.String. The UserCount property is assigned the type Int16 because it is used to represent an integer value.

Once you define a profile, whenever someone requests a page from the Web site ASP.NET automatically generates a class named ProfileCommon that corresponds to the profile definition. This class is stored in the Temporary ASP.NET Files directory, and an instance of this class is made available through the profile property of the HttpContext object.

The following section shows how to utilize this class to access the profile properties.

Working with User Profiles from an ASP.NET Page

Once you have the profiles declared, the next step is to access the profile object from within the ASP.NET page so that you can set or get the values stored in the profile properties. The following code uses the Name and UserCount properties declared in the previous section:

<%@ Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
    Profile.UserCount += 1;
}
void btnGetProfileValues_Click(object sender, EventArgs e)
{
    lblName.Text = Profile.Name;
    lblUserCount.Text = Profile.UserCount.ToString();
}
void btnSetName_Click(object sender, EventArgs e)
{
    Profile.Name = txtName.Text;
  }
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title>Accessing Profile object from an ASP.NET Page</title>
</head>
<body>
<form id="form1" runat="server">
  <div>
    Name : <asp:TextBox runat="server" ID="txtName" />
    <asp:Button runat="server" ID="btnSetName"
      Text="Set Name" OnClick="btnSetName_Click" /><br />
    <br/><br/>
    <asp:Panel ID="Panel1" runat="server"
      Height="224px" Width="265px" BorderColor="LightGray"
      BorderStyle="Dotted">
      <asp:Button runat="server" ID="btnGetProfileValues"
        Text="Get Profile Values"
        OnClick="btnGetProfileValues_Click" />
      <br/> <br /><br/>
      Profile Values: <br />
      Name: <asp:Label runat="server" ID="lblName"/>
      <br/>
      UserCount: <asp:Label runat="server" ID="lblUserCount"/>
    </asp:Panel>
  </div>
</form>
</body>
</html>

The above listing declares two command buttons. The first, btnSetName, assigns the name entered in the textbox to the Profile.Name property. The click event of the second command button, btnGetProfileValues, results in the values of the profile properties being displayed in the label controls that in turn are contained in a Panel control. In the Page_Load event, the UserCount property is incremented by 1. As you can see from the code listing, setting the value of a profile property is very simple:

Profile.Name = txtName.Text;

Similarly, retrieving the values stored in the profile object is also very simple and straightforward:

lblName.Text = Profile.Name;

Note that you don't need to typecast when retrieving the profile values because the properties stored in the profile object are strongly typed. Navigate to the above page using your browser, set the name, and click on the Get Profile Values button. You should see an output similar to Figure 1.


(Full Size Image)

Figure 1. Output from "Get Profile Values"

This example enabled Windows authentication through IIS and enabled impersonation through the following settings in the web.config file:

<identity impersonate="true"/>

Note that it enabled impersonation so that the ASP.NET code has sufficient permissions to create a new SQL Server Express database for the first time.

How Profile Properties Are Stored

You might be wondering where exactly the profile properties Name and UserCount are stored in the above example. By default, ASP.NET 2.0 comes with two profile providers: SQL Server Express and SQL Server. By default, the SQL Server Express provider is used. (A later section will show how to change the provider.)

If you refresh your project listing in Solution Explorer, you will notice a database file called ASPNETDB.MDF within the App_Data folder. If you double-click on this database, you will see that the database is opened through the Server Explorer view. Within this database, you will see a table called aspnet_Profile. Figure 2 shows the contents of the table and the values that have been saved through the Profile properties shown in the previous example.


(Full Size Image)

Figure 2. Contents of Table and Values in Profile Properties


Defining Profile Groups

Sometimes, you may want to group the related properties into a profile group so that you can easily work with them from your ASP.NET page. For example, the following profile declaration creates a group named UserPreferences that is made up of properties named BackGroundColor, ForeColor, and FontSize:

<configuration
 xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   <system.web>
      <profile>
         <properties>
            <group name="UserPreferences">
               <add name="BackgroundColor" type="System.String"/>
               <add name="ForeColor" type="System.String"/>
               <add name="FontSize" type="System.Int16"/>
            </group>
         </properties>
      </profile>
      -----
      -----
   </system.web>
</configuration>
Note: You can have multiple profile group declarations inside the <profile> element. The next section shows how to access the UserPreferences profile group from within an ASP.NET page.

Working with Profile Groups from an ASP.NET Page

The ASP.NET page shown below has two command buttons that drive the functionality of the page:

<%@ Page Language="C#" %>
<script runat="server">
void btnGetProfileValues_Click(object sender, EventArgs e)
{
    lblBackground.Text = Profile.UserPreferences.BackgroundColor;
    lblForeColor.Text = Profile.UserPreferences.ForeColor;
    lblFontSize.Text = Profile.UserPreferences.FontSize.ToString();
    Panel1.BackColor = System.Drawing.Color.FromName
      (Profile.UserPreferences.BackgroundColor);
    Panel1.ForeColor = System.Drawing.Color.FromName
      (Profile.UserPreferences.ForeColor);
    Panel1.Font.Size = FontUnit.Parse
      (Profile.UserPreferences.FontSize.ToString());
}

void btnSetValues_Click(object sender, EventArgs e)
{
    Profile.UserPreferences.BackgroundColor = txtBackColor.Text;
    Profile.UserPreferences.ForeColor = txtForeColor.Text;
    Profile.UserPreferences.FontSize =
      Convert.ToInt16(txtFontSize.Text);
  }
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title>Accessing Profile Groups from an ASP.NET Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
    BackColor: <asp:TextBox runat="server" ID="txtBackColor"/><br/>
    ForeColor: <asp:TextBox runat="server" ID="txtForeColor"/><br/>
    Font Size: <asp:TextBox runat="server" ID="txtFontSize"/><br/>
    <asp:Button runat="server" ID="btnSetName"
      Text="Set Profile Values" OnClick="btnSetValues_Click"/><br/>
    <br/><br/>
    <asp:Panel ID="Panel1" runat="server" Height="224px"
      Width="265px" BorderColor="LightGray" BorderStyle="Dotted">
      <asp:Button runat="server" ID="btnGetProfileValues"
        Text="Get Profile Values" OnClick="btnGetProfileValues_Click" />
      <br/> <br/><br/>
      Profile Values: <br />
      Back Color: <asp:Label runat="server"
                             ID="lblBackground"/><br/>
      Fore Color: <asp:Label runat="server"
                             ID="lblForeColor"/><br/>
      Font Size: <asp:Label runat="server" ID="lblFontSize"/>
    </asp:Panel>
  </div>
</form>
</body>
</html>

When the first command button (named btnSetValues) is clicked, the page sets the values of the Profile.UserPreferences group to appropriate values. When the second command button (named btnGetProfileValues) is clicked, it simply retrieves the values of the Profile.UserPreferences group and displays them in label controls. In addition, it sets various properties of the Panel control, such as BackColor, ForeColor, and Size, to the values retrieved from the Profile object.

Accessing the profile group properties is very similar to accessing the regular profile properties. The only difference is that you need to fully qualify the profile property with the profile group name, as shown below:

    Profile.UserPreferences.BackgroundColor = txtBackColor.Text;
    Profile.UserPreferences.ForeColor = txtForeColor.Text;

If you request the page from the browser, set the values of the Profile.UserPreferences group using the "Set Profile Values" and then hit the "Get Profile Values" command button. You should see an output somewhat similar to Figure 3.


(Full Size Image)

Figure 3. Output from "Get Profile Values"

As you can see from the above output, the Panel control's related properties are assigned from the profile object.

Using Profiles with Anonymous Users

The previous examples explained how to utilize the profile feature with users who log in using integrated Windows authentication. Sometimes, you will need to store data in the profile object for anonymous users as well. To accomplish this, you must first enable another ASP.NET 2.0 feature: anonymous identification. You also must mark properties in the <profile> section with a special boolean attribute: allowAnonymous. The following code demonstrates how to set up the web.config file to allow for anonymous users:

<configuration
   xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   <system.web>
      <anonymousIdentification enabled="true"/>
         <profile>
            <properties>
               <add name="Name" allowAnonymous="true"
                    type="System.String"/>
               <add name="UserCount"
                    allowAnonymous="true"
                    type="System.Int16"/>
            </properties>
         </profile>
         -----
         -----
   </system.web>
</configuration>

Choosing Profile Providers

As mentioned before, ASP.NET 2.0 ships with two providers: SQL Server Express and SQL Server. The default provider is SQL Server Express. To change to the SQL Server provider (or your own), use the ASP.NET Web Application Administration tool. Under the Provider tab, click "Select a different provider for each feature (advanced)" and then select the relevant provider in the Profile Provider box.

In addition to the default providers, you might need to create and use a custom profile provider (for example, you already have a database that stores user information, such as an employee database, or you need to use a database other than SQL Server or in some other format such as XML files). ASP.NET 2.0 also provides the ability to serve the properties stored in a user profile through different profile providers. This provides you the flexibility to manage data from different profile providers from multiple data sources for users of your application using a single user profile.

Design Personalization-Related Features

Profile is a very useful feature in ASP.NET 2.0. The object enables you to automatically store user information across multiple visits to a Web application by providing a generic storage system. You can store any type of information within a user profile, including both simple data types such as strings and integers and complex types such as custom objects.

If you need to design personalization-related features in your Web application, you will find that the new ASP.NET 2.0 Profile object will greatly simplify the design and implementation.

About the Author

Thiru Thangarathinam has six years of experience in architecting, designing, developing, and implementing applications using object-oriented application development methodologies. He also possesses a thorough understanding of the software life cycle (design, development, and testing). He holds several certifications, including MCAD for .NET, MCSD, and MCP. Thiru is an expert with ASP.NET, .NET Framework, Visual C# .NET, Visual Basic .NET, ADO.NET, XML Web services, and .NET Remoting. Thiru also has authored numerous books and articles. Contact him at thiruthangarathinam@yahoo.com.


,
WEB/ASP.NET With C# 2007. 4. 20. 14:30

[MSDN] ASP.NET 2.0 내부 변경 사항

[링크 : http://www.microsoft.com/korea/msdn/library/ko-kr/dev/aspdotnet/Internals.aspx]

ASP.NET 2.0 내부 변경 사항

Jayesh Patel, Bryan Acker, Robert McGovern
Infusion Development

2004년 8월

적용 대상:
   Microsoft ASP.NET 2.0

요약: ASP.NET 2.0은 이전 버전인 ASP.NET 1.1과 완벽하게 호환되지만, ASP.NET의 많은 요소들이 내부적으로 변경되었습니다. 변경된 요소에는 코드 모델, 컴파일, 페이지 주기 등이 있습니다. 이 기사에서는 이러한 변경 사항에 대해 간단히 설명합니다(21페이지/인쇄 페이지 기준).

목차

소개
코드 모델
컴파일
실행 중에 전체 컴파일(코드 디렉터리)
페이지 주기
확장성
고급 캐싱 기술
성능
결론

소개

전문 ASP.NET 개발자에게 있어서 ASP.NET 2.0의 큰 문제점은 내부 변경 사항과 연관되어 있습니다. 새로운 기능을 배우는 것은 흥미롭고 재미있습니다. 더욱이, ASP.NET 핵심 구조의 변경 사항은 해당 기술을 숙달하고자 하는 개발자에게 보다 큰 흥밋거리로 다가옵니다. 이 백서에서는 버전 1.x 이후의 ASP.NET 2.0 내부 구조 변경 사항에 대해 알아봅니다.

이 백서에서 다루는 항목은 성능을 중요시하는 개발자 및 기술 설계자가 응용 프로그램을 미세 조정하는 데 유용합니다. 특히 코드 모델, 컴파일, 페이지 주기, 확장성, 성능 및 캐싱과 같은 주요 영역에 대해 살펴봅니다.

이 문서에 사용된 대부분의 예를 이해하려면 ASP.NET, Visual Basic .NET 및/또는 C# 구문에 익숙해야 합니다. 해당하는 경우에는 특정 주제에 대한 자세한 설명을 볼 수 있도록 참조 문서가 제공되어 있습니다.

코드 모델

ASP.NET 2.0에서 가장 명백하게 나타나는 내부 변경 사항은 ASP.NET 웹 페이지를 만드는 방법입니다. 이 섹션에서는 코드 숨김 모델의 변경 사항 및 이 변경 사항이 ASP.NET 개발에 미치는 영향에 대해 설명합니다.

ASP.NET 1.x의 코딩 모델

ASP.NET 1.x에서는 개발자가 Web Form을 개발할 때 선택할 수 있는 두 가지 주요 옵션이 있었습니다. 첫째로, 개발자는 일반 ASP 모델에 따라 ASPX 페이지에서 직접 코드를 작성할 수 있었습니다. 코드 인라인이라는 이 과정은 단순한 명령에는 적합합니다. 그러나 보다 복잡한 코드의 경우 코드 인라인을 작성하면 표현(HTML)과 기능(코드)이 혼합된 웹 페이지를 읽기가 어려워집니다. ASP.NET의 기본 코딩 작업은 이러한 문제를 해결하기 위해 변경되었습니다. 코드 숨김 파일이라는 별도의 코드 전용 파일에서 비즈니스 논리 및 이벤트 처리 코드를 작성할 수 있습니다. 코드 숨김 모델은 프레젠테이션 태그가 포함된 ASPX 파일에 코드 전용 파일을 연결합니다. 표현과 코드를 분리함으로써 개발 팀에서 디자이너는 프레젠테이션 파일에서 작업하고 개발자는 코드 파일에서 작업하도록 하여 보다 신속하게 작업할 수 있습니다.

그림 1. ASP.NET 1.x 코딩 모델

코드 숨김 모델의 주요 문제점은 코드 숨김 파일을 ASPX 페이지와 동기화하는 방법이었습니다. 프로그래밍 관점에서 볼 때 ASPX 페이지가 코드 숨김 파일에서 상속되는 경우에도, 사실 두 파일은 더욱 복잡한 관계로 연결되어 있었습니다.

ASP.NET 1.x의 코드 숨김 모델에 대한 자세한 내용은 MSDN Library 기사 Web Forms 코드 모델 을 참조하십시오.

상속의 복잡성

ASP.NET의 디자인 패러다임은 개발자가 Microsoft Visual Studio .NET을 사용하여 컨트롤을 ASPX 페이지에 끌어 놓는 것이었습니다. 그러면 Visual Studio에서 코드 숨김 파일에 적합한 지원 코드를 자동으로 생성합니다. 컨트롤을 ASPX 페이지에 추가하면 새 코드를 코드 숨김 파일에 추가해야 합니다. 즉, 코드 숨김 파일이 ASPX 페이지에서 상속되는 경우에도 ASPX 페이지는 실제로 코드 숨김 파일의 디자인을 사용합니다.

컴파일의 복잡성

동기화의 두 번째 문제는 파일 컴파일 방법이었습니다. 모든 코드 숨김 파일은 지원 클래스와 함께 어셈블리로 컴파일되어 웹 응용 프로그램의 /bin 디렉터리에 저장됩니다. 컴파일 단계는 응용 프로그램 배포 이전에 이루어지는 반면, ASPX 페이지는 페이지를 처음 요청할 때 실행 중에 컴파일됩니다. ASP.NET 런타임은 실제로 ASPX 페이지를 고유한 임시 어셈블리로 컴파일합니다.

이 과정에서 발생하는 문제는 코드 숨김 어셈블리가 업데이트되지 않는 상태에서 ASPX 페이지를 변경할 수 있다는 점입니다. 즉, 개발자는 배포 후 ASPX 페이지에서 속성을 수정하거나 컨트롤의 형식을 변경할 수 있습니다. 이때 코드 숨김 파일은 업데이트되지 않으며 응용 프로그램 어셈블리도 다시 컴파일되지 않습니다. 이러한 경우 코드 숨김 파일과 연결된 ASPX 페이지가 일치하지 않기 때문에 응용 프로그램에서 예기치 않은 오류가 발생할 수 있습니다.

ASP.NET 2.0의 코딩 모델

ASP.NET 2.0에서도 코드 인라인 및 코드 숨김 코딩 모델을 모두 제공합니다. 코드 인라인 모델의 경우 Microsoft Visual Studio 2005에서 단일 파일 개발을 지원하는 방식을 제외하고는 거의 변경된 것이 없습니다. Visual Studio 2005의 변경 사항 및 코드 인라인 처리 방법에 대한 자세한 내용은 이 기사 를 참조하십시오.

ASP.NET 2.0에서는 코드 숨김 파일의 특성을 수정하여 코드 숨김 모델의 상속 및 컴파일 문제를 모두 해결했습니다. ASP.NET 2.0에서 코드 숨김 파일은 더 이상 System.Web.UI.Page 클래스의 완전한 구현이 아니며, 부분 클래스라는 새로운 구조로 되어 있습니다. 부분 클래스에는 사용자가 정의한 코드가 모두 포함되어 있지만, ASP.NET 1.x의 Visual Studio .NET에서 자동으로 생성된 모든 통로 및 연결 코드는 생략되어 있습니다. 새 코드 숨김 파일이 있는 ASPX 페이지를 요청하면 ASP.NET 2.0 런타임이 실제로 ASPX 페이지와 부분 클래스를 별도의 두 클래스가 아닌 단일 클래스로 결합합니다.

그림 2. ASP.NET 2.0의 코드 숨김 모델

부분 클래스에서는 새 키워드(Visual Basic의 Expands 또는 C#의 Partial)를 사용하여 실행 중에 클래스의 코드가 다른 클래스와 병합되도록 지정합니다. 마찬가지로, ASPX 페이지에서는 compilewith라는 새 지시문을 사용하여 코드 숨김 파일과 연결되도록 지정합니다.

코드 숨김 파일 비교

일반 ASP.NET 1.x 코드 숨김 파일에 친숙한 경우 Visual Studio에서 자동으로 생성된 컨트롤 선언 및 초기화 코드를 삽입한다는 것을 알고 있을 것입니다. 자동으로 생성된 이 코드는 코드 숨김 파일과 ASPX 파일이 양방향으로 동기화되어 직접적으로 생기는 결과입니다. 레이블이 있는 일반 ASPX 페이지에는 자동으로 생성된 여러 텍스트 줄로 구성된 해당 코드 숨김 파일이 있습니다.

목록 1. ASP.NET 1.x의 코드 숨김 파일

namespace WebApplication1
{
  public class WebForm1 : System.Web.UI.Page에서
  {
    protected System.Web.UI.WebControls.Label Label1;
    private void Page_Load(object sender, 
      System.EventArgs e) {    }
    #region Web Form Designer generated code
      override protected void OnInit(EventArgs e)
      {
        InitializeComponent();
        base.OnInit(e);
      }
      private void InitializeComponent()
      {    
        this.Load += new System.EventHandler(this.Page_Load);
      }
      #endregion
  }
}

자동으로 생성된 코드는 레이블(굵게 표시된 줄)을 정의할 뿐 아니라 새 이벤트(페이지 로드)를 선언하고 자동으로 생성된 메서드 래퍼(Page_Load())에 이 이벤트를 자동으로 연결하기도 합니다.

이에 비해 ASP.NET 2.0에서 같은 ASP.NET 페이지는 훨씬 깔끔한 코드 숨김 파일을 생성합니다.

목록 2. ASP.NET 2.0의 코드 숨김 파일

namespace ASP {
public partial class Webform1_aspx
{
}
}

개발자는 Label1에 자동으로 액세스하여 필요에 따라 이벤트를 추가할 수 있습니다. 예를 들어 Page_Load 이벤트를 추가하여 레이블을 초기화할 수 있습니다.

목록 3. 새 코드 숨김 파일의 이벤트 추가 작업

namespace ASP {
public partial class Webform1_aspx
{
  void Page_Load(object sender, EventArgs e)
  {
    Label1.Text = "Hello ASP.NET 2.0";
  }
}
}

이벤트 구문은 Visual Studio .NET을 통해 생성할 수 있습니다. 결과로 생성되는 코드 숨김 파일은 길이가 훨씬 짧고 자동 생성 코드가 없습니다. ASP.NET 런타임은 코드 숨김 파일의 이벤트를 ASPX의 컨트롤에 자동으로 연결합니다. 즉, ASP.NET 런타임은 이제 Visual Studio에서 수행했던 코드 생성 작업을 자동으로 수행합니다.

상속의 복잡성

새 코드 숨김 모델에서는 상속의 복잡성이 크게 줄었습니다. ASPX 페이지가 코드 숨김 파일에서 직접 상속되지 않으므로, 코드 숨김 파일은 ASPX 페이지에서 정의되는 모든 컨트롤을 더 이상 정의 및 지원하지 않아도 됩니다. 마찬가지로 코드 숨김 파일은 ASP.NET 1.x에서는 필요했던 선언 코드가 없어도 ASPX 페이지에서 컨트롤에 자동으로 액세스할 수 있습니다. ASP.NET 런타임이 필요한 선언 및 이벤트 작성 코드를 컴파일된 최종 파일에 자동으로 삽입하기 때문에 이 모든 기능이 가능한 것입니다. 런타임이 이 작업을 처리하므로 코드 개발자나 웹 개발자는 이에 대해 신경쓰지 않아도 됩니다.

디자인하는 동안 링크는 Visual Studio 2005에서 관리됩니다. Visual Studio 환경에서는 ASP.NET 런타임 컴파일을 사용하여 코드 개발자와 웹 개발자가 동기화하면서 작업할 수 있도록 합니다.

컴파일의 복잡성

새 코드 숨김 파일은 ASPX 페이지에 결합되고 실행 중에 완전한 단일 클래스로 컴파일되기 때문에 컴파일이 전혀 복잡하지 않습니다. 즉, 코드 숨김 파일은 ASPX 페이지와 자동으로 동기화됩니다. 새 컴파일 모델을 사용해도 코드가 동기화되지 않을 수 있지만, 그 결과로 발생하는 예외가 훨씬 명확하기 때문에 문제점을 빨리 파악할 수 있습니다.

컴파일

ASP.NET 1.x에 도입된 페이지 모델로 인해 ASP.NET 웹 페이지의 컴파일 과정은 항상 두 단계로 나눠져 있었습니다. 먼저 코드 숨김 파일 및 기타 지원 클래스가 어셈블리로 컴파일된 다음, 실행 중에 개별 ASPX 파일이 컴파일됩니다. 이 모델에는 많은 장점이 있지만 몇 가지 단점도 있습니다. ASP.NET 2.0에서는 사용자의 특정 요구에 따라 보다 광범위한 컴파일 옵션을 제공함으로써 이 기본 모델에 대한 몇 가지 대안을 제공합니다.

ASP.NET 1.x의 컴파일

ASP.NET 1.x의 기본 컴파일 모델은 요청된 각 ASPX 페이지에 대해 하나의 응용 프로그램 어셈블리(컴파일된 모든 코드 숨김 파일 및 기타 소스 코드 포함) 및 하나의 임시 어셈블리를 만들었습니다. 일괄 처리와 같은 컴파일러 최적화로 인해 임시 ASPX 페이지가 동일한 어셈블리로 컴파일되는 경우도 있습니다. 두 가지 경우 모두 각 ASPX 페이지는 임시 어셈블리로 컴파일되기 때문에 ASP.NET 런타임으로 로드할 수 있습니다.

그림 3. ASP.NET 1.x의 컴파일

이 모델에는 장점도 있지만, 두 가지 주요 단점이 있습니다. 첫째로, ASPX 페이지는 읽을 수 있는 형식으로 웹 사이트에 배포해야 합니다. 개발자가 코드 인라인 모델을 사용한 경우에는 일부 또는 전체 비즈니스 논리를 프로덕션 서버에서 배포할 수도 있습니다. 원시 ASPX 페이지를 제공하지 않도록 IIS 및 ASP.NET을 구성한 경우에도, 기술력이 높은 공격자는 웹 서버 액세스를 통해 여전히 파일에 액세스할 수 있습니다. 둘째로, ASP.NET 런타임이 ASPX 페이지를 컴파일해야 하기 때문에 웹 페이지를 처음 요청할 때는 응답이 보통 때보다 늦습니다.

개발자가 이 프로세스에 대해 제어할 수 있는 유일한 사항은 ASPX 페이지 일괄 컴파일 여부입니다. ASP.NET 1.x에서는 <compilation> 태그를 수정하여 web.config 파일에서 일괄 컴파일을 구성할 수 있습니다.

목록 4. 일괄 컴파일 구성

<compilation  
  batch="true|false"
  batchTimeout="시간(초)"            
  maxBatchSize="일괄 컴파일당 최대 페이지 수"
  maxBatchGeneratedFileSize="일괄 컴파일당 생성되는 
   소스 파일의 최대 결합 크기(KB)"          
</compilation>(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

일괄 컴파일을 사용하면 웹 페이지를 처음 요청할 때 시작 시간은 길어지는 대신 로드 시간이 줄어듭니다. 일괄 컴파일의 두 번째 장점은 모든 ASPX 파일이 페이지당 하나의 임시 어셈블리로 컴파일되지 않고 단일 임시 어셈블리로 컴파일된다는 점입니다.

ASP.NET 2.0의 컴파일

ASP.NET 2.0에서는 웹 응용 프로그램에 대해 다음과 같은 4가지 컴파일 모델을 제공합니다.

  • 일반(ASP.NET 1.x)-일반 ASP.NET 웹 응용 프로그램에서 코드 숨김 파일은 어셈블리로 컴파일되어 /bin 디렉터리에 저장됩니다. 요청 시 웹 페이지(ASPX)가 컴파일됩니다. 이 모델은 대부분의 웹 사이트에 적합합니다. 그러나 컴파일 프로세스로 인해 처음 ASP.NET 페이지를 요청할 때 후속 요청에 비해 속도가 느립니다. ASP.NET 2.0에서도 이 컴파일 모델을 지원합니다.
  • 일괄 컴파일-ASP.NET 2.0에서는 단일 URL 요청으로 응용 프로그램을 일괄 컴파일할 수 있습니다. ASP.NET 1.x를 사용할 때와 마찬가지로, 일괄 컴파일을 사용하면 처음 페이지를 요청할 때는 지연되지 않지만 시작 시 주기 시간이 길어집니다. 또한 일괄 컴파일을 사용하려면 여전히 코드 숨김 파일을 컴파일하여 미리 배포해야 합니다.
  • 미리 컴파일하여 배포-ASP.NET 2.0의 새 기능을 사용하면 배포하기 전에 프로젝트를 완전히 컴파일할 수 있습니다. 전체 컴파일에서 응용 프로그램의 크기와 컴파일 설정에 따라 모든 코드 숨김 파일, ASPX 페이지, HTML, 그래픽 리소스 및 기타 백엔드 코드가 실행 가능한 하나 이상의 어셈블리로 컴파일됩니다. 이 어셈블리에는 웹 사이트의 컴파일된 코드가 모두 포함되며, 리소스 파일 및 구성 파일이 수정되지 않고 복사됩니다. 이 컴파일 방법을 사용하면 성능과 보안을 최상으로 유지할 수 있지만 배포 후에 웹 사이트를 수정할 수는 없습니다. 굉장히 시각적이거나 안전한 웹 사이트로 작업하는 경우 이 옵션은 최종적으로 배포할 때 적합합니다. 그러나 로컬 인트라넷에서 실행되며 자주 변경되는 소규모 사이트를 만드는 경우 미리 전체를 컴파일하는 작업은 불필요합니다.
  • 실행 중에 전체 컴파일-미리 컴파일하여 배포하는 방법과 반대로, ASP.NET 2.0에서는 실행 중에 전체 응용 프로그램을 컴파일하는 새 메커니즘을 제공합니다. 즉, 컴파일되지 않은 코드 숨김 파일 및 기타 관련 코드를 새 코드 디렉터리에 배치한 다음 실행 중에 이 파일로부터 생성될 어셈블리의 참조를 ASP.NET 2.0에서 자동으로 만들어 유지하도록 할 수 있습니다. 이 옵션을 사용하면 가장 융통성 있게 웹 사이트 콘텐츠를 변경할 수 있지만 컴파일되지 않은 코드를 서버에 저장해야 합니다.

환경과 요구 사항에 가장 적합한 컴파일 옵션을 선택할 수 있지만, 컴파일 모델에는 항상 융통성이 있습니다. 코드 디렉터리를 사용하여 코드 숨김 파일을 저장하는 경우에도 전체 컴파일 방법을 사용하여 응용 프로그램을 배포할 수 있습니다.

일괄 컴파일

ASP.NET 2.0에서도 web.config 일괄 컴파일 설정을 사용할 수 있습니다. 일괄 컴파일의 장점은 첫 사용자가 페이지를 즉시 사용할 수 있으며, 일괄 컴파일 작업 중에 ASPX 페이지의 오류가 검색된다는 점입니다. 그러나 일괄 컴파일을 사용하면 응용 프로그램을 시작할 때 지연이 발생하며 web.config 파일에서 일괄 컴파일을 구성해야 합니다.

미리 컴파일하여 배포

미리 컴파일하여 배포하는 경우 웹 사이트의 실행 파일 버전인 어셈블리를 하나 이상 만들 수 있습니다. 그 결과로 생기는 어셈블리에는 웹 사이트의 컴파일 코드가 포함됩니다. HTML 페이지, 리소스, 구성 파일 및 ASPX 페이지는 별도로 복사됩니다.

미리 컴파일하여 배포하려면 aspnet_compiler.exe라는 명령줄 유틸리티를 사용해야 합니다. 이 유틸리티는 대상 배포 디렉터리를 만드는데, 이 디렉터리에는 다양한 ASPX 페이지의 어셈블리 및 스텁 파일이 있는 /bin 디렉터리가 포함되어 있습니다. 이 유틸리티를 사용하면 "magic page"(마법 페이지)를 호출하는 동작과 비슷하게 현재 위치에서 미리 컴파일할 수도 있습니다. 스텁 파일은 ASPX 페이지와 이름이 같지만 컴파일된 어셈블리로 호출되는 단순 코드를 포함하고 있습니다. 즉, ASPX 페이지는 완전한 기능을 갖춘 페이지라기보다는 단순히 빈 셸입니다.

웹 사이트를 미리 구성하여 배포하면 어셈블리를 디컴파일하지 않고서는 코드에 액세스할 수 없기 때문에 보안이 크게 향상됩니다. 보안을 더욱 향상시키려면 컴파일의 결과물인 어셈블리를 판독하기 어렵게 처리하여 웹 응용 프로그램을 더욱 안전하게 만들 수 있습니다. 미리 컴파일하여 배포하는 방법의 가장 큰 단점은 이 단계를 배포 전에 수행해야 하기 때문에 배포한 후에는 웹 사이트를 변경할 수 없다는 점입니다. 웹 사이트를 변경하려면 웹 사이트를 다시 컴파일하여 다시 배포해야 합니다.

미리 컴파일하여 배포하는 옵션은 웹 서버에 배포되는 원시 코드의 양을 줄이고 최고의 보안을 제공하기 때문에 대부분의 주요 웹 응용 프로그램에서 배포에 사용되는 메커니즘입니다. 생산성을 크게 저하시키지 않고 이 향상된 프로세스를 일반 개발/테스트/배포 주기에 포함할 수 있습니다.

실행 중에 전체 컴파일(코드 디렉터리)

지금까지 설명한 세 가지 컴파일 방법 모두, 배포하기 전에 모든 코드 파일(코드 숨김 파일 및 지원 클래스)을 컴파일해야 합니다. ASP.NET 2.0에서는 코드 디렉터리를 사용할 수 있습니다.

코드 디렉터리는 컴파일되지 않은 클래스를 보관하는 특수 디렉터리입니다. 실행 중에 ASP.NET 런타임은 응용 프로그램에서 ASPX 페이지가 자동으로 참조하는 어셈블리로 이 디렉터리의 콘텐츠를 컴파일합니다. 즉, 코드 디렉터리를 사용함으로써 지원 코드에 대해 별도의 어셈블리를 만들고 참조하지 않아도 됩니다. 코드 디렉터리의 장점은 프로젝트를 완전히 컴파일하지 않고 배포할 수 있으므로 잠재적인 불일치 문제를 줄일 수 있다는 점이며, 단점은 서버에서 컴파일되지 않은 코드가 노출된다는 점입니다.

이 옵션은 코드 숨김 파일 또는 외부 개체의 형식으로 지원 코드가 많이 필요하지 않은 ASP.NET 응용 프로그램에 적합합니다. 간단한 응용 프로그램의 경우에는 시스템을 빠르게 배포 및 테스트할 수 있는 방법을 사용하는 것이 보다 강력한 컴파일 방법을 사용하는 것에 비해 더 유리합니다.

페이지 주기

ASP.NET 2.0에서는 ASP.NET 페이지의 주기에서 두 가지 주요 사항이 변경되었습니다. 첫째로, ASP.NET 2.0에서는 새 이벤트를 제공하여 마스터 페이지, 개인 설정, 통합 모바일 장치 지원 등의 새 기능을 지원합니다. 둘째로, ASP.NET 2.0에는 Web Forms의 페이지 간 게시 기능이 도입되었습니다.

새 이벤트

ASP.NET 2.0에서는 ASP.NET 1.x에 비해 보다 세분화된 페이지 주기 메서드 스택을 제공합니다. 추가된 메서드는 웹 개발자에게 보다 향상된 제어 기능을 제공합니다. ASP.NET 페이지의 Page 개체를 통해 이러한 이벤트에 액세스할 수 있습니다.

표 1은 광범위한 메서드 목록을 보여 줍니다. 메서드 열에는 실제 이벤트 메서드 이름이 표시되며, 활성 열은 이벤트가 항상 활성 상태인지 아니면 PostBack 작업 동안에만 활성화되는지를 나타냅니다. 예를 들어 새 TestDeviceFilter 메서드를 사용하여 어떤 장치 필터가 있는지 확인할 수 있으며 이 정보를 통해 페이지 표시 방법을 결정할 수 있습니다. 반면에 새 LoadControlState 메서드는 포스트백(postback) 동안에만 활성화됩니다. SaveControlState와 함께 이 메서드를 재정의하여 포스트백(postback) 동안 컨트롤 상태를 저장 및 복원하기 위한 대체 serialization 구성표를 만들 수 있습니다.

표 1. 페이지 주기 메서드

메서드 활성
Constructor 항상
Construct 항상
TestDeviceFilter 항상
AddParsedSubObject 항상
DeterminePostBackMode 항상
OnPreInit 항상
LoadPersonalizationData 항상
InitializeThemes 항상
OnInit 항상
ApplyControlSkin 항상
ApplyPersonalization 항상
OnInitComplete 항상
LoadPageStateFromPersistenceMedium PostBack
LoadControlState PostBack
LoadViewState PostBack
ProcessPostData1 PostBack
OnPreLoad 항상
OnLoad 항상
ProcessPostData2 PostBack
RaiseChangedEvents PostBack
RaisePostBackEvent PostBack
OnLoadComplete 항상
OnPreRender 항상
OnPreRenderComplete 항상
SavePersonalizationData 항상
SaveControlState 항상
SaveViewState 항상
SavePageStateToPersistenceMedium 항상
Render 항상
OnUnload 항상

페이지 주기에 대해 간단히 살펴보면, 테마와 개인 설정 같이 ASP.NET 2.0에서 사용할 수 있는 여러 기능이 자연스럽게 구현되는 위치를 볼 수 있습니다. 예를 들어 테마는 IntializeThemes 이벤트에서 처리되며 개인 설정 데이터는 LoadPersonalizationData에서 로드된 다음 나중에 ApplyPersonalization 메서드에서 적용됩니다. 어떤 UI 요소가 웹 응용 프로그램의 최종적인 모양과 느낌을 결정하는지와 관련하여 메서드 순서는 매우 중요합니다.

페이지 간 게시

페이지 주기의 두 번째 주요 변경 사항은 포스트백(post back) 이벤트 및 Web Forms 관련 사항입니다. ASP.NET 1.x에서는 Web Forms가 호스트 페이지로 자동 포스트백(postback)됩니다. 즉, 사용자가 양식을 제출하면 양식 데이터는 원래 양식이 포함된 페이지로 항상 다시 전송됩니다. 이 방법으로 디자인하면 컨트롤 상태를 쉽게 저장할 수 있지만 개발자가 보다 복잡한 작업을 수행하는 데 제한이 있습니다.

ASP.NET 2.0에서는 개발자가 양식 데이터를 제출하는 위치를 결정할 수 있는 새 속성이 Web Form 컨트롤에 포함되어 있습니다. 대부분의 경우에는 포스트백(postback) 메커니즘이 적합하므로 여전히 이 메커니즘이 기본값입니다. 그러나 이제 개발자는 다른 데이터를 다른 양식에 게시할 수도 있습니다.

그림 4. 포스트백(Postback) 및 페이지 간 게시

예를 들어 여러 가지 양식으로 구성된 다중 페이지 마법사를 만들 수 있습니다. 최종 유효성 검사가 발생할 수 있는 요약 페이지에 도달할 때까지 각 양식은 순서대로 다음 페이지로 제출됩니다. PreviousPage 개체를 사용하여 현재 컨텍스트에서 마지막 페이지의 데이터에 액세스할 수 있습니다. PreviousPage 개체는 현재 페이지에 사용할 수 있도록 이전 페이지에서 유효성을 검사한 데이터를 저장합니다. 이 개체 덕분에 페이지 간 게시를 사용할 때 컨트롤을 유지할 수 있습니다. 시퀀스에서 양식 한 개를 백업해야 하는 경우 페이지 데이터에 즉시 액세스할 수 있으며 모든 데이터를 다시 입력할 필요가 없습니다.

확장성

ASP.NET은 원래 개방형 프레임워크로 디자인되었습니다. 즉, ASP.NET을 구성하는 대부분의 모듈 및 구성 요소를 필요에 맞게 확장, 수정 또는 대체할 수 있습니다. ASP.NET 2.0에서는 이제 프레임워크의 표준이 된 새 HTTPHandlersHTTPModules를 통해 프레임워크의 확장성을 더욱 명확하게 확인할 수 있습니다.

요청 파이프라인

ASP.NET에서 요청은 웹 서버로부터 ISAPI(인터넷 서버 응용 프로그래밍 인터페이스) 필터를 통해 실제 ASP.NET 런타임으로 전달됩니다.

그림 5. 요청 파이프라인

IIS에서 요청을 받으면 IIS 설정에 따라 확장명이 ISAPI 필터에 매핑됩니다. .aspx, .asmx, .asd 등의 확장명은 aspnet_isapi.dll로 매핑됩니다. aspnet_isapi.dll은 ASP.NET 런타임을 시작하는 ISAPI 필터입니다. 요청이 발생하면 ASP.NET 런타임은 ASP.NET 웹 응용 프로그램의 호스트 역할을 하는 HTTPApplication 개체에서 시작됩니다. HTTPApplication 개체는 다음과 같은 동작을 수행합니다.

  1. 컴퓨터 및 응용 프로그램 수준의 구성 파일을 읽습니다.
  2. 하나 이상의 HTTPModule 인스턴스를 통해 요청을 전달합니다. 각 HTTPModule은 세션 유지 관리, 인증 또는 프로필 유지 관리와 같은 서비스를 제공합니다. 이 모듈은 요청을 다시 HTTPApplication으로 전달합니다.
  3. 동사 및 경로를 기준으로 요청을 HTTPHandler로 전달합니다. 동사는 요청(GET, POST, FTP 등)에 사용된 HTTP 동사를 참조하며, 경로는 응용 프로그램 내의 URL을 참조합니다. 처리기를 구성하는 방법에 따라 요청을 ASP.NET 페이지로 처리할 수도 있고, 요청으로 인해 모든 웹 페이지의 일괄 컴파일 등 다른 동작이 호출될 수도 있습니다(System.Web.UI.PageIHTTPHandler를 구현한 것이며 precomiplation.asd는 PrecompHandler를 호출함).

ASP.NET 2.0에서도 이 모델은 그대로 유지되지만, 다양한 모듈 및 처리기가 새로 추가되어 더 많은 서비스를 제공합니다. ASP.NET 1.x에서와 마찬가지로 모듈 또는 처리기 클래스를 확장, 대체 또는 재구성하여 사용자 지정 기능을 제공할 수 있습니다.

새 모듈

HTTPModules가 추가되어 ASP.NET 2.0에서 제공되는 새로운 서비스를 지원합니다. 특히 기본 모듈 설정이 지정된 ASP.NET 응용 프로그램에는 다음에 대한 새 모듈이 포함됩니다.

  • SessionID-ASP.NET 1.x 세션 모듈에서 세션 ID 메커니즘이 분리되어 쿠키, URL 다시 작성 및 기타 세션 ID 생성 양식을 보다 효과적으로 제어할 수 있습니다.
  • 역할 관리-새 모듈이 추가되어 새 사용자 ID 메커니즘을 지원하는 역할 기반 서비스를 제공합니다. 이 모듈을 사용하면 .NET 프레임워크에 구축된 역할 기반 보안에 ASP.NET 응용 프로그램을 쉽게 연결할 수 있습니다.
  • 익명 ID-새 개인 설정 기능은 익명 사용자를 지원합니다. 이 모듈을 사용하면 익명 사용자가 액세스할 수 있는 기능 및 요청 간에 이 기능이 유지 관리되는 방법을 파악할 수 있습니다.
  • 프로필-프로필 모듈은 새 프로필 서비스에 연결되며 사용자별 영구 데이터 저장소를 제공할 수 있도록 합니다.
  • 페이지 카운터-ASP.NET 2.0은 새 모듈을 통합하여 페이지 카운터에 연결하고 웹 트래픽의 통계 분석 기능을 향상시킵니다.

이러한 새 모듈 외에도, 일부 이전 모듈의 동작이 변경되었습니다. 예를 들어 출력 캐싱 모듈은 이 백서 뒷부분에 설명할 새 캐싱 기술을 지원합니다.

새 처리기

새 모듈 외에도, ASP.NET 2.0에는 응용 프로그램 구성 도구 및 일괄 컴파일 요청 등의 기타 새 기능을 지원하는 처리기가 새로 추가되었습니다. 새 처리기 중 가장 중요한 처리기에는 웹 사이트 관리 요청을 처리하는 ".axd" 패밀리가 있습니다. 이 처리기는 개발자가 ASP.NET 사용자 및 기타 설정을 구성할 수 있도록 하는 내부 관리 도구를 시작합니다. 이러한 관리 처리기는 다음과 같습니다.

  • 웹 관리-WebAdminHandler는 관리 웹 사이트의 기본 페이지입니다. 이 처리기를 사용하여 ASP.NET 2.0 웹 응용 프로그램 관리를 시작할 수 있습니다.
  • 추적-ASP.NET 1.x TraceHandler가 향상되었습니다. 이 처리기는 ASP.NET 1.x에서 사용할 수 있었던 유일한 "axd" 처리기입니다.
  • 웹 리소스-새 관리 도구 및 WebResourcesHandler를 통해 이제 웹 리소스를 배포 후에 구성할 수 있습니다.
  • 캐시된 이미지-CachedImageServiceHandler는 그래픽 구성 요소 캐싱을 지원합니다.
  • 카운터-SiteCountersHandler를 페이지 카운터 모듈과 함께 사용하여 ASP.NET 2.0 응용 프로그램의 액세스 통계를 제공합니다.
  • 미리 컴파일-앞에서 언급한 대로, PrecompHandler를 사용하여 ASP.NET 응용 프로그램의 모든 ASPX 페이지를 일괄 컴파일할 수 있습니다.
  • 웹 파트 내보내기-WebPartExportHandler는 웹 파트 레이아웃의 저장 및 전송을 지원합니다. 웹 파트는 포털형 웹 응용 프로그램의 모양과 콘텐츠를 개인 설정할 수 있는 새로운 메커니즘입니다.

일반적인 경우와 같이 HTTPForbiddenHandler는 반환해서는 안 되는 파일 형식에 연결됩니다. ASP.NET 2.0에서는 금지된 파일 형식의 범위가 보다 넓어져서 마스터 페이지, 스킨 파일 및 기타 새 개발자 구성 요소가 포함됩니다.

고급 캐싱 기술

웹 응용 프로그램의 성능을 향상시킬 수 있는 한 가지 방법은 메모리에서 정적 콘텐츠를 캐시하는 것입니다. 캐시된 콘텐츠는 새로 렌더링된 콘텐츠보다 항상 빠르게 반환됩니다. 하지만 단점은 캐시된 콘텐츠가 오래되어 내용이 부실해질 수 있다는 것입니다. ASP.NET 1.x에서는 다음을 비롯하여 여러 가지 캐싱을 지원합니다.

  • 페이지 수준-각 페이지를 전체적으로 캐시하거나 페이지에 액세스하는 데 사용된 매개 변수를 기반으로 캐시할 수 있습니다. 캐시된 페이지는 지정한 시간이 지나면 만료됩니다.
  • 페이지 조각-사용자 컨트롤(.ascx 파일)을 사용하여 페이지를 만든 경우 나머지 페이지 콘텐츠와 별도로 이 사용자 컨트롤을 캐시할 수 있습니다.
  • 프로그래밍 방식 캐싱-개발자는 캐시 API를 통해 개체를 캐시할 수도 있습니다. 캐시 API 사용의 확실한 이점은 캐시를 플러시해야 하는 경우를 위해 다른 종류의 종속성을 만들 수 있다는 것입니다.

ASP.NET 2.0에서는 페이지 수준의 캐싱 메커니즘이 확장되어 데이터베이스 종속성을 지원합니다. 데이터베이스 캐시 종속성을 사용하면 캐시된 페이지를 SQL Server 데이터베이스의 특정 테이블에 연결할 수 있습니다. 테이블이 변경되면 캐시가 자동으로 만료됩니다. 또한 개발자는 이제 사후 캐시 대체 기능을 사용하여 캐시된 콘텐츠의 일부를 새로 고친 콘텐츠로 바꿀 수 있습니다. 사후 캐시 대체를 사용하면 페이지의 일부를 동적으로 생성해야 하는 경우에도 응용 프로그램에서 페이지 수준의 캐싱을 사용할 수 있습니다.

데이터베이스 캐시 무효화

대부분의 데이터 기반 웹 사이트에서 캐싱은 어려운 문제일 수 있습니다. 특히 캐싱이 필요한 상황에서 최신 데이터가 필요한 경우에는 더욱 그러합니다. ASP.NET 1.x에서 페이지는 지정한 시간 동안 캐시할 수 있었으며, 입력 매개 변수(쿼리 문자열 또는 POST 매개 변수)에 의해 구성되었습니다.

목록 5. ASP.NET 1.x 출력 캐시 지시문

<%@ outputcache duration="3600" varybyparam="ProdID" %> 

예를 들어 목록 5의 코드는 ProdID 변수를 기반으로 한 시간 동안 메모리에서 페이지를 캐시합니다. 위의 예에서 발생하는 문제점은 관련 업무 데이터가 다른 곳에서 업데이트되는 경우 수행해야 하는 작업입니다. 예를 들어 제품 카탈로그 페이지가 제품 ID에 의해 캐시되는 경우를 가정해 봅시다. 가능한 수량이나 가격 등 이 제품에 대한 정보가 관리 사이트에서 업데이트되는 경우 잘못된 데이터가 캐시되어 고객에게 표시됩니다. 이전 버전의 ASP.NET에서 이 문제를 해결하려면 Response.RemoveOutputCacheItem을 사용하여 캐시에서 페이지를 수동으로 제거하거나 duration 시간이 만료될 때까지 기다린 후 시스템에서 자동으로 페이지를 업데이트하도록 해야 했습니다.

ASP.NET 2.0에서는 데이터베이스 캐시 종속성을 지원하므로 이러한 문제가 해결됩니다. SQL Server 7 및 2000에서 작업할 경우 테이블 수준 알림을 사용할 수 있으며, Microsoft SQL Server 2005에서는 보다 세분화된 수준으로 알림을 제공합니다. 예를 들어 다음 코드는 최대 한 시간 동안 제품 페이지를 캐시하지만 데이터베이스 테이블에 두 번째 종속성을 추가합니다.

목록 6. ASP.NET 2.0 데이터베이스 캐시의 예

<%@ outputcache duration="3600" 
  varybyparam="ProdID" 
  sqldependency="MyDatabase:Products" %>

sqldependency 특성을 사용하면 Products 테이블이 변경될 경우 캐시된 페이지가 만료됩니다. sqldependency 특성은 web.config 파일에서 구성된 datasource를 참조해야 합니다. datasource는 데이터베이스 연결 및 필요한 매개 변수를 식별하여 종속성 알림 작업을 수행합니다.

사용자 지정 캐시 종속성

ASP.NET 2.0에는 Microsoft SQL Server를 지원하는 단일 CacheDependency 구현인 SQLCacheDependency 클래스가 있습니다. 새 캐시 종속성을 구현하는 작업은 포함된 프로세스이지만, ASP.NET 2.0의 확장성으로 인해 구현이 가능합니다. 즉, 사용자 고유의 CacheDependency 클래스를 만들어 Oracle이나 Sybase 등의 다른 데이터베이스 시스템과 유사한 기능을 제공할 수 있습니다.

사후 캐시 대체

일부 페이지 요소는 동적으로 유지되지만 페이지에서 대부분의 요소가 캐시를 사용하는 경우, ASP.NET 2.0에서는 사후 캐시 대체라는 기능을 제공합니다. 사후 캐시 대체는 페이지를 사용자에게 표시하기 전에 캐시된 페이지에 있는 특정 요소를 다시 계산해야 함을 ASP.NET 런타임에 알리는 데 사용됩니다.

다음 두 가지 방법으로 이 기능을 사용할 수 있습니다.

  • Response.writeSubstitution 메서드를 호출하고 대체 콜백 함수에 대한 참조를 전달합니다.
  • 웹 페이지에 <asp:substitution> 컨트롤을 추가하고 methodname 특성을 콜백 함수의 이름으로 설정합니다.
  • 어떤 옵션을 사용하든지 종속성의 기간과 위치를 지정하는 @OutputCache 지시문을 페이지에 추가해야 합니다.

사후 캐시 대체 구현

사후 캐시 대체를 인식하는 컨트롤을 만들어 이 기능을 활용할 수 있습니다. 이러한 컨트롤의 예로는 AdRotator 컨트롤을 들 수 있습니다. 목록 7은 다음과 같은 페이지를 나타냅니다.

  • Pubs 데이터베이스의 작성자 테이블에서 데이터를 검색하는 페이지
  • 데이터를 GridView 컨트롤에 결합하는 페이지
  • AdRotator에서 광고를 표시하는 페이지
  • 레이블 컨트롤에 페이지를 만든 시간을 표시하는 페이지

목록에서 굵게 표시된 <asp:substitution> 컨트롤도 이 예에 추가되었습니다. 이 컨트롤은 문자열 출력(이 경우 현재 시간)을 반환하는 메서드인 uncachedUpdatemethodname 특성을 설정합니다. 이 대체 컨트롤은 캐시된 대상과 상관없이 정확한 시간을 반환합니다.

목록 7. PostCache.ASPX 소스 코드

<%@ Page language="c#" Codebehind="PostCache.ASPX.cs" 
  AutoEventWireup="true" Inherits="WebApplication1.PostCache" %>
<%@ outputcache duration="30" varybyparam="none" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
  <HEAD>
    <title>WebForm1</title>
  </HEAD>
  <body MS_POSITIONING="GridLayout">
    <form id="Form1" method="post" runat="server">
      <DIV style="DISPLAY: inline;
        Z-INDEX: 101; LEFT: 32px; WIDTH: 160px;
        POSITION: absolute; TOP: 24px; HEIGHT: 8px"
        align="right" ms_positioning="FlowLayout">
          this page was created at:
      </DIV>
      <asp:Label id="CreatedTime"
        style="Z-INDEX: 102; LEFT: 200px; POSITION: absolute;
        TOP: 24px" runat="server" Width="120px" Height="16px">
      </asp:Label>
      <asp:substitution id="UpdatedTime" methodname="uncachedUpdate"
        style="Z-INDEX: 103; LEFT: 200px; POSITION: absolute;
        TOP: 48px" runat="server" Width="112px" Height="11px">
      </asp:substitution>
      <DIV style="DISPLAY: inline; Z-INDEX: 104; LEFT: 32px;
        WIDTH: 160px; POSITION: absolute; TOP: 48px;
        HEIGHT: 16px" align="right" ms_positioning="FlowLayout">
          and last updated at:
      </DIV>
      <asp:AdRotator id="Ads" style="Z-INDEX: 105; LEFT: 312px;
        POSITION: absolute; TOP: 16px" runat="server"
        Width="80px" Height="60px" AdvertisementFile="img/Ads.xml">
      </asp:AdRotator>
    </form>
  </body>
</HTML>

이 페이지의 코드 숨김 파일에는 uncachedUpdate 메서드에서 사후 캐시 대체를 지원하는 데 필요한 이벤트가 포함됩니다. Page_Load 메서드는 페이지를 로드한 시간을 보고하므로 캐싱이 발생하는 시간을 파악할 수 있습니다.

목록 8. PostCache.ASPX.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebApplication1 {
  public class PostCache : System.Web.UI.Page  {
    protected System.Web.UI.WebControls.Label CreatedTime;
    protected System.Web.UI.WebControls.Label UpdatedTime;
    protected System.Web.UI.WebControls.AdRotator Ads;

    private void InitializeComponent()  {
      this.Load += new System.EventHandler(this.Page_Load);
    }

    private void Page_Load(object sender, System.EventArgs e) {
      CreatedTime.Text = DateTime.Now.ToShortTimeString();  
    }

    protected String uncachedUpdate()  {
      return DateTime.Now.ToShortTimeString();
    }
  }
}

사후 캐시 대체 기능 사용

그림 6은 PostCache 페이지의 출력을 보여 줍니다. 응용 프로그램을 처음 실행할 때 "Page created time"과 "Last updated time"이 일치하는 것을 볼 수 있습니다.

그림 6. PostCache.ASPX의 출력

이후에 같은 페이지를 호출하면 사후 캐시 대체의 효과를 확인할 수 있습니다. Page created time과 이미지는 동일하게 유지되지만 Last updated time은 변경됩니다.

그림 7. 두 번째 요청 시 PostCache 출력

캐싱 지시문으로 인해 Page created time과 adRotator 이미지는 일정하게 유지됩니다. 페이지는 30초 동안 캐시됩니다. 이 시간이 지나면 다음 요청 시 Page created time과 adRotator가 업데이트됩니다. 그러나 uncachedUpdate() 메서드를 호출하는 <asp:substitution> 컨트롤은 캐시된 상태와 상관없이 페이지가 요청될 때마다 업데이트됩니다.

사후 캐시 대체를 적절히 사용하면 개발자는 페이지의 동적 부분만 업데이트함으로써 웹 응용 프로그램의 성능을 크게 향상시킬 수 있습니다. ASP.NET 2.0에서 개발한 웹 응용 프로그램을 데이터베이스 캐시 무효화 및 비동기 페이지 업데이트 기능과 함께 사용하면 웹의 일반 요청 및 응답 아키텍처로 인해 발생하는 여러 제한 사항을 없앨 수 있습니다.

성능

ASP.NET 2.0의 인프라 변경 사항 및 추가 기능에 대해 설명했습니다. 그러나 아직 ASP.NET 2.0의 성능에 관한 의문 사항이 남아 있습니다. ASP.NET 2.0이 아직 개발 중이기 때문에 성능 메트릭을 사용할 수는 없지만, ASP.NET 2.0 프레임워크의 모든 면에 걸쳐 성능을 유지하거나 향상시키는 데 많은 노력을 기울여 왔습니다.

향상된 요청 파이프라인

모든 개발자가 향상된 성능을 확인할 수 있는 영역은 요청 파이프라인입니다. 많은 이벤트가 새로 추가되었지만, 기본 ASP.NET 요청 스택은 ASP.NET 1.1의 요청 스택보다 최대 30% 빠릅니다. "Hello World"를 표시하는 간단한 페이지를 만들어 향상된 성능을 평가할 수 있습니다. 이 페이지에는 고급 기능이 없기 때문에 ASP.NET 2.0을 IIS에 연결하는 ISAPI 플러그 인을 비롯하여 HTTPHandlerHTTPModule 파이프라인을 직접 테스트할 수 있습니다. 보다 빠른 처리를 위해 이 코드가 최적화되었기 때문에 사용 중인 IIS 버전에 상관없이 향상된 성능을 확인할 수 있습니다.

IIS 6.0으로 향상된 메모리 관리

ASP.NET 2.0에서는 IIS 6.0을 함께 사용할 때만 성능이 향상되는 경우가 있습니다. 예를 들어 IIS 6.0의 경우 100명의 사용자가 동시에 여러 개의 컨트롤이 있는 페이지를 요청하는 로드 테스트에서 작업자 프로세스의 작업 집합이 약 50% 감소되었습니다. 이러한 결과는 지정된 서버의 경우 운영 체제에서 이전에 필요했던 리소스에 비해 절반 정도의 리소스만 사용함을 의미합니다.

어느 정도 복잡한 ASP.NET 페이지를 테스트한 결과, 같은 페이지를 IIS 5.0에서 실행했을 때에 비해 시스템 로드(메모리 및 CPU 사용량)가 크게 낮아졌습니다. 이러한 성능 향상은 관리 메모리에서 고유 메모리로 응답 버퍼를 이동함으로써 가능해진 것입니다. ASP.NET 2.0에서는 관리 메모리를 특정 응답에 고정할 필요가 없으므로 리소스 병목 현상이 없으며 각 요청에 대해 응답이 보다 빨리 생성됩니다.

기타 성능 향상은 IIS 6.0과 Windows 운영 체제 커널을 견고하게 통합하여 이룬 것입니다. IIS 6.0에서는 커널 수준에서 일부 캐싱 및 버퍼링을 수행하므로 ASP.NET을 비롯한 모든 웹 응용 프로그램의 성능이 향상됩니다.

기타 향상된 기능

개발자는 ASP.NET 2.0의 기능 수행 속도가 ASP.NET 1.x와 같거나 더 빠르다는 것을 알게 될 것입니다. 핵심 기능이 모두 포함된 최종 ASP.NET 2.0 릴리스에서는 더 많은 성능 향상을 확인할 수 있습니다.

결론

ASP.NET 2.0에서는 개발자의 생산성을 높이기 위해 다양한 구조적 기능이 향상되었습니다. 코드 모델이 향상되어 충돌을 줄이고, 컴파일 프로세스가 확장되어 웹 응용 프로그램을 컴파일 및 배포하는 옵션이 보다 다양하게 제공됩니다. ASP.NET 프레임워크의 확장성은 개인 설정, 마스터 페이지, 관리 사이트 등을 비롯하여 ASP.NET의 여러 가지 새 기능을 지원하는 새 HTTPModulesHTTPHandlers를 통해 다시 한 번 확인되었습니다. 데이터베이스 종속성과 사후 캐시 대체를 사용할 수 있도록 캐싱이 향상되었습니다. 내부적으로 ASP.NET 2.0에는 이전 버전에 비해 크게 향상된 기능이 포함되어 있습니다. ASP.NET 2.0의 새로운 구현 방식은 업계 최고의 방식을 따르는 동시에 다양한 개발자 중심의 향상된 기능을 통합합니다. ASP.NET 2.0에서는 복잡한 엔터프라이즈 웹 응용 프로그램 개발 작업을 처리할 수 있는 세계 최고의 웹 개발 플랫폼을 제공합니다.

관련 서적



저자 소개

Jayesh Patel-.NET 및 Java Technologies의 개발자입니다. Jay의 주요 연구 분야는 패턴 기반 프로그래밍 및 효율적인 방법론입니다.

Bryan Acker-Infusion Development의 기술 전문 저술가입니다. Bryan은 ASP 및 ASP.NET 웹 개발과 웹 호스팅 분야에서 많은 경력을 쌓았습니다.

Robert McGovern-Infusion Development의 수석 저술가, 개발자 및 프로젝트 관리자입니다. Rob은 CodeNotes for ASP.NET 및 JSP to ASP.NET Migration Guide 등 여러 가지 ASP.NET 프로젝트에 참여했습니다.

Infusion Development Corporation은 재무 서비스 업계를 중점적으로 Fortune지 선정 100대 기업에 사용자 지정된 소프트웨어 개발, 교육 및 컨설팅 서비스를 제공하는 Microsoft Certified Solutions Provider입니다. 뉴욕과 토론토에 지사를 두고 있는 Infusion Development는 재무 서비스, 보안 중개 및 소프트웨어 개발 업계의 세계 최대 회사를 비롯하여 전 세계에 고객을 보유하고 있습니다. Infusion Development의 직원들 역시 CodeNotes 서적 시리즈의 저자 및 작성자입니다.

화면 맨 위로화면 맨 위로
,
WEB/IIS 2007. 4. 20. 14:16

IIS 6.0 Error : HTTP 오류 403.1 - 거부됨: 실행 권한이 거부되었습니다.

이 페이지를 표시할 수 없습니다.

프로그램 실행이 허용되지 않는 디렉터리에서 CGI, ISAPI 또는 다른 실행 프로그램을 실행하려고 했습니다.

다음을 시도하십시오.

  • 이 디렉터리에 대한 실행 권한을 갖고 있는 경우 웹 사이트 관리자에게 문의하십시오.

HTTP 오류 403.1 - 거부됨: 실행 권한이 거부되었습니다.
IIS(인터넷 정보 서비스)


기술 정보(지원 인력용)

  • Microsoft 고객기술지원부로 이동하여 HTTP403이라는 단어로 제목을 검색하십시오.
  • IIS 관리자(inetmgr)에서 액세스할 수 있는 IIS 도움말을 열어 ISAPI 확장 구성, CGI 응용 프로그램 구성, 웹 사이트 권한 설정을 통한 사이트 보안사용자 지정 오류 메시지 항목을 검색하십시오.
  • IIS SDK(Software Development Kit)나 MSDN 온라인 라이브러리에서 ISAPI 확장 개발, ISAPI 및 CGI, ISAPI 확장 및 필터 디버깅 항목을 검색하십시오.


디렉토리에 권한 추가.
권한 추가후에도 이렇다면 IIS에서 실행권한 확인 : 없음 => 스크립트 전용
,
TOTAL TODAY