데이터 액세스 레이어 만들기
이 자습서 시리즈에서는 웹용 ASP.NET 4.5 및 Microsoft Visual Studio Express 2013을 사용하여 ASP.NET Web Forms 애플리케이션을 빌드하는 기본 사항을 설명합니다. C# 소스 코드가 있는 Visual Studio 2013 프로젝트는 이 자습서 시리즈와 함께 사용할 수 있습니다.
이 자습서에서는 ASP.NET Web Forms 및 Entity Framework Code First를 사용하여 데이터베이스에서 데이터를 만들고, 액세스하고, 검토하는 방법을 설명합니다. 이 자습서는 이전 자습서 "프로젝트 만들기"를 기반으로 하며 Wingtip Toy Store 자습서 시리즈의 일부입니다. 이 자습서를 완료하면 프로젝트의 Models 폴더에 있는 데이터 액세스 클래스 그룹을 빌드하게 됩니다.
학습할 내용:
- 데이터 모델을 만드는 방법
- 데이터베이스를 초기화하고 시드하는 방법입니다.
- 데이터베이스를 지원하도록 애플리케이션을 업데이트하고 구성하는 방법입니다.
자습서에 도입된 기능은 다음과 같습니다.
- Entity Framework Code First
- LocalDB
- 데이터 주석
데이터 모델 만들기
Entity Framework 는 ORM(개체 관계형 매핑) 프레임워크입니다. 관계형 데이터를 개체로 사용할 수 있으므로 일반적으로 작성해야 하는 대부분의 데이터 액세스 코드를 제거할 수 있습니다. Entity Framework를 사용하여 LINQ를 사용하여 쿼리를 실행한 다음 강력한 형식의 개체로 데이터를 검색하고 조작할 수 있습니다. LINQ는 데이터를 쿼리하고 업데이트하기 위한 패턴을 제공합니다. Entity Framework를 사용하면 데이터 액세스 기본 사항에 집중하지 않고 애플리케이션의 나머지 부분을 만드는 데 집중할 수 있습니다. 이 자습서 시리즈의 뒷부분에서는 데이터를 사용하여 탐색 및 제품 쿼리를 채우는 방법을 보여 줍니다.
Entity Framework는 Code First라는 개발 패러다임을 지원합니다. Code First를 사용하면 클래스를 사용하여 데이터 모델을 정의할 수 있습니다. 클래스는 기타 형식, 메서드 및 이벤트의 변수를 그룹화하여 자체 사용자 지정 형식을 만들 수 있는 구문입니다. 클래스를 기존 데이터베이스에 매핑하거나 이를 사용하여 데이터베이스를 생성할 수 있습니다. 이 자습서에서는 데이터 모델 클래스를 작성하여 데이터 모델을 만듭니다. 그런 다음 Entity Framework가 이러한 새 클래스에서 즉시 데이터베이스를 만들도록 합니다.
먼저 Web Forms 애플리케이션의 데이터 모델을 정의하는 엔터티 클래스를 만듭니다. 그런 다음 엔터티 클래스를 관리하고 데이터베이스에 대한 데이터 액세스를 제공하는 컨텍스트 클래스를 만듭니다. 데이터베이스를 채우는 데 사용할 이니셜라이저 클래스도 만듭니다.
Entity Framework 및 참조
기본적으로 Entity Framework는 Web Forms 템플릿을 사용하여 새 ASP.NET 웹 애플리케이션을 만들 때 포함됩니다. Entity Framework를 NuGet 패키지로 설치, 제거 및 업데이트할 수 있습니다.
이 NuGet 패키지에는 프로젝트 내에서 다음 런타임 어셈블리가 포함됩니다.
- EntityFramework.dll – Entity Framework에서 사용하는 모든 공용 런타임 코드
- EntityFramework.SqlServer.dll – Entity Framework용 Microsoft SQL Server 공급자
엔터티 클래스
데이터의 스키마를 정의하기 위해 만드는 클래스를 엔터티 클래스라고 합니다. 데이터베이스 디자인을 새로운 경우 엔터티 클래스를 데이터베이스의 테이블 정의로 간주합니다. 클래스의 각 속성은 데이터베이스 테이블의 열을 지정합니다. 이러한 클래스는 개체 지향 코드와 데이터베이스의 관계형 테이블 구조 간에 간단한 개체 관계형 인터페이스를 제공합니다.
이 자습서에서는 제품 및 범주에 대한 스키마를 나타내는 간단한 엔터티 클래스를 추가하여 시작합니다. 제품 클래스에는 각 제품에 대한 정의가 포함됩니다. 제품 클래스ProductID
의 각 멤버 이름은 , , ProductName
, Description
ImagePath
, UnitPrice
, CategoryID
및 입니다Category
. 범주 클래스에는 자동차, 보트 또는 평면과 같이 제품이 속할 수 있는 각 범주에 대한 정의가 포함됩니다. 범주 클래스의 각 멤버 이름은 , , CategoryName
Description
및 Products
입니다CategoryID
. 각 제품은 범주 중 하나에 속합니다. 이러한 엔터티 클래스는 프로젝트의 기존 Models 폴더에 추가됩니다.
솔루션 탐색기Models 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 ->새 항목을 선택합니다.
새 항목 추가 대화 상자가 표시됩니다.
왼쪽의 설치된 창에서 Visual C#에서 코드를 선택합니다.
가운데 창에서 클래스 를 선택하고 이 새 클래스의 이름을 Product.cs로 지정합니다.
추가를 클릭합니다.
새 클래스 파일이 편집기에서 표시됩니다.기본 코드를 다음 코드로 바꿉니다.
using System.ComponentModel.DataAnnotations; namespace WingtipToys.Models { public class Product { [ScaffoldColumn(false)] public int ProductID { get; set; } [Required, StringLength(100), Display(Name = "Name")] public string ProductName { get; set; } [Required, StringLength(10000), Display(Name = "Product Description"), DataType(DataType.MultilineText)] public string Description { get; set; } public string ImagePath { get; set; } [Display(Name = "Price")] public double? UnitPrice { get; set; } public int? CategoryID { get; set; } public virtual Category Category { get; set; } } }
그러나 1~4단계를 반복하여 다른 클래스를 만듭니다. 그러나 새 클래스의 이름을 Category.cs 로 지정하고 기본 코드를 다음 코드로 바꿉니다.
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace WingtipToys.Models { public class Category { [ScaffoldColumn(false)] public int CategoryID { get; set; } [Required, StringLength(100), Display(Name = "Name")] public string CategoryName { get; set; } [Display(Name = "Product Description")] public string Description { get; set; } public virtual ICollection<Product> Products { get; set; } } }
앞에서 설명한 Category
것처럼 클래스는 애플리케이션이 판매하도록 설계된 제품 유형(예: "자동차", "보트", "로켓" 등)을 나타내며 Product
클래스는 데이터베이스의 개별 제품(장난감)을 나타냅니다. 개체의 각 instance 관계형 데이터베이스 테이블 내의 Product
행에 해당하며 Product 클래스의 각 속성은 관계형 데이터베이스 테이블의 열에 매핑됩니다. 이 자습서의 뒷부분에서는 데이터베이스에 포함된 제품 데이터를 검토합니다.
데이터 주석
클래스의 특정 멤버에는 와 같은 [ScaffoldColumn(false)]
멤버에 대한 세부 정보를 지정하는 특성이 있음을 알 수 있습니다. 데이터 주석입니다. 데이터 주석 특성은 해당 멤버에 대한 사용자 입력의 유효성을 검사하고, 해당 멤버에 대한 서식을 지정하고, 데이터베이스를 만들 때 모델링되는 방법을 지정하는 방법을 설명할 수 있습니다.
Context 클래스
데이터 액세스에 클래스 사용을 시작하려면 컨텍스트 클래스를 정의해야 합니다. 앞에서 설명한 것처럼 컨텍스트 클래스는 엔터티 클래스(예: Product
클래스 및 Category
클래스)를 관리하고 데이터베이스에 대한 데이터 액세스를 제공합니다.
이 절차에서는 Models 폴더에 새 C# 컨텍스트 클래스를 추가합니다.
Models 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 ->새 항목을 선택합니다.
새 항목 추가 대화 상자가 표시됩니다.가운데 창에서 클래스 를 선택하고 이름을 ProductContext.cs 로 지정하고 추가를 클릭합니다.
클래스에 포함된 기본 코드를 다음 코드로 바꿉다.
using System.Data.Entity; namespace WingtipToys.Models { public class ProductContext : DbContext { public ProductContext() : base("WingtipToys") { } public DbSet<Category> Categories { get; set; } public DbSet<Product> Products { get; set; } } }
이 코드는 강력한 형식의 개체를 사용하여 데이터를 쿼리, 삽입, 업데이트 및 삭제하는 기능을 포함하는 Entity Framework의 모든 핵심 기능에 액세스할 수 있도록 네임스페이스를 추가 System.Data.Entity
합니다.
클래스는 ProductContext
데이터베이스의 클래스 인스턴스 가져오기, 저장 및 업데이트를 Product
처리하는 Entity Framework 제품 데이터베이스 컨텍스트를 나타냅니다. 클래스는 ProductContext
Entity Framework에서 DbContext
제공하는 기본 클래스에서 파생됩니다.
이니셜라이저 클래스
컨텍스트를 처음 사용할 때 데이터베이스를 초기화하려면 몇 가지 사용자 지정 논리를 실행해야 합니다. 이렇게 하면 제품 및 범주를 즉시 표시할 수 있도록 시드 데이터를 데이터베이스에 추가할 수 있습니다.
이 절차에서는 Models 폴더에 새 C# 이니셜라이저 클래스를 추가합니다.
Models 폴더에 다른
Class
을 만들고 이름을 ProductDatabaseInitializer.cs로 지정합니다.클래스에 포함된 기본 코드를 다음 코드로 바꿉다.
using System.Collections.Generic; using System.Data.Entity; namespace WingtipToys.Models { public class ProductDatabaseInitializer : DropCreateDatabaseIfModelChanges<ProductContext> { protected override void Seed(ProductContext context) { GetCategories().ForEach(c => context.Categories.Add(c)); GetProducts().ForEach(p => context.Products.Add(p)); } private static List<Category> GetCategories() { var categories = new List<Category> { new Category { CategoryID = 1, CategoryName = "Cars" }, new Category { CategoryID = 2, CategoryName = "Planes" }, new Category { CategoryID = 3, CategoryName = "Trucks" }, new Category { CategoryID = 4, CategoryName = "Boats" }, new Category { CategoryID = 5, CategoryName = "Rockets" }, }; return categories; } private static List<Product> GetProducts() { var products = new List<Product> { new Product { ProductID = 1, ProductName = "Convertible Car", Description = "This convertible car is fast! The engine is powered by a neutrino based battery (not included)." + "Power it up and let it go!", ImagePath="carconvert.png", UnitPrice = 22.50, CategoryID = 1 }, new Product { ProductID = 2, ProductName = "Old-time Car", Description = "There's nothing old about this toy car, except it's looks. Compatible with other old toy cars.", ImagePath="carearly.png", UnitPrice = 15.95, CategoryID = 1 }, new Product { ProductID = 3, ProductName = "Fast Car", Description = "Yes this car is fast, but it also floats in water.", ImagePath="carfast.png", UnitPrice = 32.99, CategoryID = 1 }, new Product { ProductID = 4, ProductName = "Super Fast Car", Description = "Use this super fast car to entertain guests. Lights and doors work!", ImagePath="carfaster.png", UnitPrice = 8.95, CategoryID = 1 }, new Product { ProductID = 5, ProductName = "Old Style Racer", Description = "This old style racer can fly (with user assistance). Gravity controls flight duration." + "No batteries required.", ImagePath="carracer.png", UnitPrice = 34.95, CategoryID = 1 }, new Product { ProductID = 6, ProductName = "Ace Plane", Description = "Authentic airplane toy. Features realistic color and details.", ImagePath="planeace.png", UnitPrice = 95.00, CategoryID = 2 }, new Product { ProductID = 7, ProductName = "Glider", Description = "This fun glider is made from real balsa wood. Some assembly required.", ImagePath="planeglider.png", UnitPrice = 4.95, CategoryID = 2 }, new Product { ProductID = 8, ProductName = "Paper Plane", Description = "This paper plane is like no other paper plane. Some folding required.", ImagePath="planepaper.png", UnitPrice = 2.95, CategoryID = 2 }, new Product { ProductID = 9, ProductName = "Propeller Plane", Description = "Rubber band powered plane features two wheels.", ImagePath="planeprop.png", UnitPrice = 32.95, CategoryID = 2 }, new Product { ProductID = 10, ProductName = "Early Truck", Description = "This toy truck has a real gas powered engine. Requires regular tune ups.", ImagePath="truckearly.png", UnitPrice = 15.00, CategoryID = 3 }, new Product { ProductID = 11, ProductName = "Fire Truck", Description = "You will have endless fun with this one quarter sized fire truck.", ImagePath="truckfire.png", UnitPrice = 26.00, CategoryID = 3 }, new Product { ProductID = 12, ProductName = "Big Truck", Description = "This fun toy truck can be used to tow other trucks that are not as big.", ImagePath="truckbig.png", UnitPrice = 29.00, CategoryID = 3 }, new Product { ProductID = 13, ProductName = "Big Ship", Description = "Is it a boat or a ship. Let this floating vehicle decide by using its " + "artifically intelligent computer brain!", ImagePath="boatbig.png", UnitPrice = 95.00, CategoryID = 4 }, new Product { ProductID = 14, ProductName = "Paper Boat", Description = "Floating fun for all! This toy boat can be assembled in seconds. Floats for minutes!" + "Some folding required.", ImagePath="boatpaper.png", UnitPrice = 4.95, CategoryID = 4 }, new Product { ProductID = 15, ProductName = "Sail Boat", Description = "Put this fun toy sail boat in the water and let it go!", ImagePath="boatsail.png", UnitPrice = 42.95, CategoryID = 4 }, new Product { ProductID = 16, ProductName = "Rocket", Description = "This fun rocket will travel up to a height of 200 feet.", ImagePath="rocket.png", UnitPrice = 122.95, CategoryID = 5 } }; return products; } } }
위의 코드에서 볼 수 있듯이 데이터베이스를 만들고 초기화하면 속성이 재정의 Seed
되고 설정됩니다. 속성이 Seed
설정되면 범주 및 제품의 값을 사용하여 데이터베이스를 채웁니다. 데이터베이스를 만든 후 위의 코드를 수정하여 시드 데이터를 업데이트하려고 하면 웹 애플리케이션을 실행할 때 업데이트가 표시되지 않습니다. 위의 코드는 클래스의 DropCreateDatabaseIfModelChanges
구현을 사용하여 시드 데이터를 다시 설정하기 전에 모델(스키마)이 변경되었는지 여부를 인식하기 때문입니다. 및 Product
엔터티 클래스를 Category
변경하지 않으면 데이터베이스가 시드 데이터로 다시 초기화되지 않습니다.
참고
애플리케이션을 실행할 때마다 데이터베이스를 다시 만들려면 클래스 대신 클래스를 DropCreateDatabaseAlways
DropCreateDatabaseIfModelChanges
사용할 수 있습니다. 그러나 이 자습서 시리즈의 경우 클래스를 DropCreateDatabaseIfModelChanges
사용합니다.
이 자습서의 이 시점에서 4개의 새 클래스와 1개의 기본 클래스가 있는 Models 폴더가 있습니다.
데이터 모델을 사용하도록 애플리케이션 구성
이제 데이터를 나타내는 클래스를 만들었으므로 클래스를 사용하도록 애플리케이션을 구성해야 합니다. Global.asax 파일에서 모델을 초기화하는 코드를 추가합니다. Web.config 파일에서 새 데이터 클래스로 표시되는 데이터를 저장하는 데 사용할 데이터베이스를 애플리케이션에 알려주는 정보를 추가합니다. Global.asax 파일을 사용하여 애플리케이션 이벤트 또는 메서드를 처리할 수 있습니다. Web.config파일을 사용하면 ASP.NET 웹 애플리케이션의 구성을 제어할 수 있습니다.
Global.asax 파일 업데이트
애플리케이션이 시작될 때 데이터 모델을 초기화하려면 Global.asax.cs 파일에서 처리기를 업데이트 Application_Start
합니다.
참고
솔루션 탐색기 Global.asax 파일 또는 Global.asax.cs 파일을 선택하여 Global.asax.cs 파일을 편집할 수 있습니다.
노란색으로 강조 표시된 다음 코드를 Global.asax.cs 파일의
Application_Start
메서드에 추가합니다.using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Optimization; using System.Web.Routing; using System.Web.Security; using System.Web.SessionState; using System.Data.Entity; using WingtipToys.Models; namespace WingtipToys { public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { // Code that runs on application startup RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); // Initialize the product database. Database.SetInitializer(new ProductDatabaseInitializer()); } } }
참고
브라우저에서 이 자습서 시리즈를 볼 때 노란색으로 강조 표시된 코드를 보려면 브라우저에서 HTML5를 지원해야 합니다.
위의 코드에 표시된 것처럼 애플리케이션이 시작될 때 애플리케이션은 데이터에 처음 액세스할 때 실행되는 이니셜라이저를 지정합니다. 개체와 개체에 액세스 Database
하려면 두 개의 추가 네임스페이 ProductDatabaseInitializer
스가 필요합니다.
Web.Config 파일 수정
Entity Framework Code First는 데이터베이스가 시드 데이터로 채워질 때 기본 위치에 데이터베이스를 생성하지만 애플리케이션에 고유한 연결 정보를 추가하면 데이터베이스 위치를 제어할 수 있습니다. 프로젝트의 루트에 있는 애플리케이션의 Web.config 파일에서 연결 문자열을 사용하여 이 데이터베이스 연결을 지정합니다. 새 연결 문자열을 추가하여 데이터베이스의 위치(wingtiptoys.mdf)를 기본 위치가 아닌 애플리케이션의 데이터 디렉터리(App_Data)에 빌드하도록 지시할 수 있습니다. 이렇게 변경하면 이 자습서의 뒷부분에서 데이터베이스 파일을 찾아 검사할 수 있습니다.
솔루션 탐색기Web.config 파일을 찾아 엽니다.
다음과 같이 노란색으로 강조 표시된 연결 문자열을
<connectionStrings>
Web.config 파일의 섹션에 추가합니다.<connectionStrings> <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-WingtipToys-20131119102907.mdf;Initial Catalog=aspnet-WingtipToys-20131119102907;Integrated Security=True" providerName="System.Data.SqlClient" /> <add name="WingtipToys" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\wingtiptoys.mdf;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings>
애플리케이션이 처음으로 실행되면 연결 문자열에 지정된 위치에 데이터베이스를 빌드합니다. 그러나 애플리케이션을 실행하기 전에 먼저 빌드해 보겠습니다.
애플리케이션 빌드
웹 애플리케이션의 모든 클래스와 변경 내용이 작동하는지 확인하려면 애플리케이션을 빌드해야 합니다.
디버그 메뉴에서 WingtipToys 빌드를 선택합니다.
출력 창이 표시되고 모두 잘 진행되면 성공 메시지가 표시됩니다.
오류가 발생하면 위의 단계를 다시 검사. 출력 창의 정보는 문제가 있는 파일과 파일에서 변경이 필요한 위치를 나타냅니다. 이 정보를 통해 프로젝트에서 검토 및 수정해야 하는 위 단계의 일부를 확인할 수 있습니다.
요약
데이터 모델을 만든 시리즈의 이 자습서에서는 데이터베이스를 초기화하고 시드하는 데 사용할 코드를 추가했습니다. 또한 애플리케이션을 실행할 때 데이터 모델을 사용하도록 애플리케이션을 구성했습니다.
다음 자습서에서는 UI를 업데이트하고, 탐색을 추가하고, 데이터베이스에서 데이터를 검색합니다. 이렇게 하면 이 자습서에서 만든 엔터티 클래스에 따라 데이터베이스가 자동으로 만들어집니다.
추가 리소스
Entity Framework 개요
ADO.NET Entity Framework 초보자 가이드
Entity FrameworkCode First 관계 Fluent API를 사용한 코드 첫 번째 개발
Code First 데이터 주석
Entity Framework의 생산성 향상