이 비디오 및 단계별 연습에서는 새 데이터베이스를 대상으로 하는 Code First 개발을 소개합니다. 이 시나리오에는 존재하지 않는 데이터베이스를 대상으로 지정하고 Code First가 만들거나 Code First가 새 테이블을 추가할 빈 데이터베이스를 대상으로 하는 것이 포함됩니다. Code First를 사용하면 C# 또는 VB.Net 클래스를 사용하여 모델을 정의할 수 있습니다. 필요에 따라 클래스 및 속성의 특성을 사용하거나 흐름 API를 사용하여 추가 구성을 수행할 수 있습니다.
비디오 보기
이 비디오에서는 새 데이터베이스를 대상으로 하는 Code First 개발을 소개합니다. 이 시나리오에는 존재하지 않는 데이터베이스를 대상으로 지정하고 Code First가 만들거나 Code First가 새 테이블을 추가할 빈 데이터베이스를 대상으로 하는 것이 포함됩니다. Code First를 사용하면 C# 또는 VB.Net 클래스를 사용하여 모델을 정의할 수 있습니다. 필요에 따라 클래스 및 속성의 특성을 사용하거나 흐름 API를 사용하여 추가 구성을 수행할 수 있습니다.
발표자: 로완 밀러
필수 구성 요소
이 연습을 완료하려면 Visual Studio 2010 또는 Visual Studio 2012 이상이 설치되어 있어야 합니다.
Visual Studio 2010을 사용하는 경우 NuGet 도 설치해야 합니다.
1. 애플리케이션 만들기
작업을 간단하게 유지하기 위해 Code First를 사용하여 데이터 액세스를 수행하는 기본 콘솔 애플리케이션을 빌드합니다.
- Visual Studio를 엽니다.
- 파일 -> 새로 만들기 -> 프로젝트...
- 왼쪽 메뉴 및 콘솔 애플리케이션에서 Windows 선택
- CodeFirstNewDatabaseSample을 이름으로 입력합니다.
- 확인을 선택합니다.
2. 모델 만들기
클래스를 사용하여 매우 간단한 모델을 정의해 보겠습니다. Program.cs 파일에서 정의하기만 하면 되지만 실제 애플리케이션에서는 클래스를 별도의 파일과 잠재적으로 별도의 프로젝트로 분할합니다.
Program.cs Program 클래스 정의 아래에 다음 두 클래스를 추가합니다.
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
두 탐색 속성(Blog.Posts 및 Post.Blog)을 가상으로 만드는 것을 알 수 있습니다. 이렇게 하면 Entity Framework의 지연 로드 기능을 사용할 수 있습니다. 지연 로드는 액세스하려고 할 때 이러한 속성의 내용이 데이터베이스에서 자동으로 로드됨을 의미합니다.
3. 컨텍스트 만들기
이제 데이터베이스와의 세션을 나타내는 파생 컨텍스트를 정의하여 데이터를 쿼리하고 저장할 수 있습니다. System.Data.Entity.DbContext에서 파생되고 모델의 각 클래스에 대해 형식화된 DbSet<TEntity> 를 노출하는 컨텍스트를 정의합니다.
이제 Entity Framework의 형식을 사용하기 시작했으므로 EntityFramework NuGet 패키지를 추가해야 합니다.
- 프로젝트 –> NuGet 패키지 관리... 참고: NuGet 패키지 관리 옵션이 없는 경우 최신 버전의 NuGet을 설치해야 합니다.
- 온라인 탭 선택
- EntityFramework 패키지 선택
- 설치를 클릭합니다.
Program.cs 맨 위에 System.Data.Entity에 대한 using 문을 추가합니다.
using System.Data.Entity;
Program.cs Post 클래스 아래에 다음과 같은 파생 컨텍스트를 추가합니다.
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
다음은 Program.cs 포함해야 하는 항목의 전체 목록입니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace CodeFirstNewDatabaseSample
{
class Program
{
static void Main(string[] args)
{
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
}
이것이 데이터 저장 및 검색을 시작하는 데 필요한 모든 코드입니다. 분명히 무대 뒤에서 꽤 많은 일이 일어나고 있으며 잠시 후에 살펴보겠습니다.
4. 데이터 읽기 및 쓰기
아래와 같이 Program.cs Main 메서드를 구현합니다. 이 코드는 컨텍스트의 새 인스턴스를 만든 다음 이를 사용하여 새 블로그를 삽입합니다. 그런 다음 LINQ 쿼리를 사용하여 타이틀 순으로 사전순으로 정렬된 데이터베이스에서 모든 블로그를 검색합니다.
class Program
{
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
// Create and save a new Blog
Console.Write("Enter a name for a new Blog: ");
var name = Console.ReadLine();
var blog = new Blog { Name = name };
db.Blogs.Add(blog);
db.SaveChanges();
// Display all Blogs from the database
var query = from b in db.Blogs
orderby b.Name
select b;
Console.WriteLine("All blogs in the database:");
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
이제 애플리케이션을 실행하고 테스트할 수 있습니다.
Enter a name for a new Blog: ADO.NET Blog
All blogs in the database:
ADO.NET Blog
Press any key to exit...
내 데이터는 어디에 있나요?
규칙에 따라 DbContext는 사용자를 위해 데이터베이스를 만들었습니다.
- 로컬 SQL Express 인스턴스를 사용할 수 있는 경우(Visual Studio 2010으로 기본적으로 설치됨) Code First가 해당 인스턴스에 데이터베이스를 만들었습니다.
- SQL Express를 사용할 수 없는 경우 Code First는 LocalDB (Visual Studio 2012와 함께 기본적으로 설치됨)를 시도하고 사용합니다.
- 데이터베이스의 이름은 파생 컨텍스트의 정규화된 이름 뒤에 지정되며, 여기서는 CodeFirstNewDatabaseSample.BloggingContext입니다.
이는 기본 규칙일 뿐이며 Code First에서 사용하는 데이터베이스를 변경하는 다양한 방법이 있으며, 자세한 내용은 DbContext에서 모델 및 데이터베이스 연결 검색 방법 항목에서 확인할 수 있습니다. Visual Studio에서 서버 탐색기를 사용하여 이 데이터베이스에 연결할 수 있습니다.
보기 -> 서버 탐색기
데이터 연결을 마우스 오른쪽 단추로 클릭하고 연결 추가를 선택합니다...
Microsoft SQL Server를 데이터 원본으로 선택하기 전에 서버 탐색기에서 데이터베이스에 연결하지 않은 경우
설치한 항목에 따라 LocalDB 또는 SQL Express에 연결
이제 Code First에서 만든 스키마를 검사할 수 있습니다.
DbContext는 정의한 DbSet 속성을 확인하여 모델에 포함할 클래스를 확인했습니다. 그런 다음 코드 첫 번째 규칙의 기본 집합을 사용하여 테이블 및 열 이름을 확인하고, 데이터 형식을 결정하고, 기본 키를 찾습니다. 이 워크스루의 뒷부분에서는 이러한 규칙을 재정의하는 방법을 살펴보겠습니다.
5. 모델 변경 처리
이제 모델을 몇 가지 변경해야 합니다. 이러한 변경을 할 때 데이터베이스 스키마도 업데이트해야 합니다. 이를 위해 Code First 마이그레이션 또는 간단히 마이그레이션이라는 기능을 사용할 것입니다.
마이그레이션을 사용하면 데이터베이스 스키마를 업그레이드(및 다운그레이드)하는 방법을 설명하는 순서가 지정된 단계 집합을 사용할 수 있습니다. 마이그레이션이라고 하는 이러한 각 단계에는 적용할 변경 내용을 설명하는 일부 코드가 포함되어 있습니다.
첫 번째 단계는 BloggingContext에 Code First 마이그레이션을 사용하도록 설정하는 것입니다.
도구 -> 라이브러리 패키지 관리자 -> 패키지 관리자 콘솔
패키지 관리자 콘솔에서 Enable-Migrations 명령 실행
다음 두 항목을 포함하는 새 마이그레이션 폴더가 프로젝트에 추가되었습니다.
- Configuration.cs – 이 파일에는 마이그레이션에서 BloggingContext 마이그레이션에 사용할 설정이 포함되어 있습니다. 이 연습에서는 아무것도 변경할 필요가 없지만 여기서는 시드 데이터를 지정하고, 다른 데이터베이스에 공급자를 등록하고, 마이그레이션이 생성되는 네임스페이스를 변경하는 등의 작업을 수행할 수 있습니다.
- <timestamp>_InitialCreate.cs – 첫 번째 마이그레이션이며, 데이터베이스가 빈 데이터베이스에서 블로그 및 게시물 테이블을 포함하는 데이터베이스로 가져오기 위해 이미 적용된 변경 내용을 나타냅니다. Code First에서 이러한 테이블을 자동으로 생성하도록 허용했지만, 이제 마이그레이션 기능을 선택하여 이를 변환하였습니다. 또한 Code First는 이 마이그레이션이 이미 적용되었음을 로컬 데이터베이스에 기록했습니다. 파일 이름의 타임스탬프는 순서 지정을 위해 사용됩니다.
이제 모델을 변경하고 블로그 클래스에 Url 속성을 추가해 보겠습니다.
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual List<Post> Posts { get; set; }
}
- 패키지 관리자 콘솔에서 Add-Migration AddUrl 명령을 실행합니다. Add-Migration 명령은 마지막 마이그레이션 이후 변경 내용을 확인하고 발견된 변경 내용으로 새 마이그레이션을 스캐폴드합니다. 마이그레이션에 이름을 지정할 수 있습니다. 이 경우 마이그레이션 'AddUrl'을 호출합니다. 스캐폴딩 코드는 문자열 데이터를 저장할 수 있는 URL 열을 dbo.Blogs 테이블에 추가해야 한다고 말합니다. 필요한 경우 스캐폴드된 코드를 편집할 수 있지만 이 경우에는 필요하지 않습니다.
namespace CodeFirstNewDatabaseSample.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class AddUrl : DbMigration
{
public override void Up()
{
AddColumn("dbo.Blogs", "Url", c => c.String());
}
public override void Down()
{
DropColumn("dbo.Blogs", "Url");
}
}
}
- 패키지 관리자 콘솔에서 Update-Database 명령을 실행합니다. 이 명령은 보류 중인 모든 마이그레이션을 데이터베이스에 적용합니다. InitialCreate 마이그레이션이 이미 적용되었으므로 마이그레이션은 새 AddUrl 마이그레이션만 적용합니다. 팁: Update-Database 호출할 때 –Verbose 스위치를 사용하여 데이터베이스에 대해 실행 중인 SQL을 확인할 수 있습니다.
이제 새 URL 열이 데이터베이스의 블로그 테이블에 추가됩니다.
6. 데이터 주석
지금까지는 EF가 기본 규칙을 사용하여 모델을 검색하도록 허용했지만, 클래스가 규칙을 따르지 않고 추가 구성을 수행할 수 있어야 하는 경우가 있습니다. 여기에는 두 가지 옵션이 있습니다. 이 섹션의 데이터 주석과 다음 섹션의 흐름 API를 살펴보겠습니다.
- 모델에 사용자 클래스를 추가해 보겠습니다.
public class User
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
- 또한 파생 컨텍스트에 집합을 추가해야 합니다.
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}
- 마이그레이션을 추가하려고 하면 "EntityType 'User'에 키가 정의되어 있지 않습니다. 이 EntityType에 대한 키를 정의합니다." EF는 사용자 이름이 사용자의 기본 키여야 한다는 것을 알 방법이 없기 때문입니다.
- 이제 데이터 주석을 사용하므로 Program.cs 맨 위에 using 문을 추가해야 합니다.
using System.ComponentModel.DataAnnotations;
- 이제 Username 속성에 주석을 추가하여 기본 키임을 식별합니다.
public class User
{
[Key]
public string Username { get; set; }
public string DisplayName { get; set; }
}
- Add-Migration AddUser 명령을 사용하여 마이그레이션을 스캐폴드하여 이러한 변경 내용을 데이터베이스에 적용합니다.
- Update-Database 명령을 실행하여 데이터베이스에 새 마이그레이션 적용
이제 새 테이블이 데이터베이스에 추가됩니다.
EF에서 지원하는 주석의 전체 목록은 다음과 같습니다.
- KeyAttribute
- StringLengthAttribute
- MaxLengthAttribute
- ConcurrencyCheckAttribute
- RequiredAttribute
- TimestampAttribute
- ComplexTypeAttribute
- ColumnAttribute
- TableAttribute
- InversePropertyAttribute
- ForeignKeyAttribute
- DatabaseGeneratedAttribute
- NotMappedAttribute
7. Fluent API
이전 섹션에서는 데이터 주석을 사용하여 규칙에 의해 검색된 내용을 보완하거나 재정의하는 방법을 살펴보았습니다. 모델을 구성하는 다른 방법은 Code First Fluent API를 사용하는 것입니다.
대부분의 모델 구성은 간단한 데이터 주석을 사용하여 수행할 수 있습니다. Fluent API는 데이터 주석으로는 가능하지 않은 고급 구성 외에도 데이터 주석이 수행할 수 있는 모든 작업을 포함하는 모델 구성을 지정하는 고급 방법입니다. 데이터 주석과 흐름 API를 함께 사용할 수 있습니다.
흐름 API에 접근하려면 DbContext에서 OnModelCreating 메서드를 재정의해야 합니다. User.DisplayName이 저장된 열의 이름을 display_name으로 변경하고자 한다고 가정해 보겠습니다.
- 다음 코드를 사용하여 BloggingContext에서 OnModelCreating 메서드 재정의
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.DisplayName)
.HasColumnName("display_name");
}
}
- Add-Migration ChangeDisplayName 명령을 사용하여 마이그레이션을 스캐폴드하여 이러한 변경 내용을 데이터베이스에 적용합니다.
- Update-Database 명령을 실행하여 데이터베이스에 새 마이그레이션을 적용합니다.
이제 DisplayName 열의 이름이 display_name으로 변경되었습니다.
요약
이 연습에서는 새 데이터베이스를 사용한 Code First 개발을 살펴보았습니다. 클래스를 사용하여 모델을 정의한 다음, 해당 모델을 사용하여 데이터베이스를 만들고 데이터를 저장하고 검색했습니다. 데이터베이스가 만들어지면 모델이 발전함에 따라 Code First 마이그레이션을 사용하여 스키마를 변경했습니다. 또한 데이터 주석 및 Fluent API를 사용하여 모델을 구성하는 방법도 알아보았습니다.
.NET