엔터티 간의 관계를 만드는 방법은 무엇입니까?
Entity Framework Code First 접근 방식을 사용하면 모델을 일반 클래스로 만든 다음 도메인 모델 또는 엔터티 클래스에서 데이터베이스를 만들 수 있습니다. Code First 접근 방식에서는 데이터베이스에서 데이터베이스가 만들어집니다.
Entity Framework Code First 접근 방식의 몇 가지 장점은 다음과 같습니다 (Scott Gu의 블로그에 명시 된대로).
- 디자이너를 열거나 XML 매핑 파일을 정의할 필요 없이 개발
- 기본 클래스가 필요하지 않은 "일반 오래된 클래스"를 작성하여 모델 객체를 정의합니다.
- 명시 적으로 아무것도 구성하지 않고 데이터베이스 지속성을 가능하게하는 "convention over configuration"접근 방식을 사용합니다.
- 선택적으로 규칙 기반 지속성을 재정의하고 유창한 코드 API를 사용하여 지속성 매핑을 완전히 사용자 지정합니다.
이론적인 개념에 대해 더 자세히 알아보기 위해 이 게시물에서는 코드로 직접 이동하여 Code First 접근 방식을 사용하여 테이블과 데이터베이스를 만듭니다. 이 게시물에서는 Entity Framework Code First 접근 방식에서 엔터티와 엔터티 간의 관계를 만드는 방법을 배웁니다. EF Code First 접근 방식에는 다음을 통해 엔터티 간의 관계를 만드는 두 가지 옵션이 있습니다.
- 데이터 주석
- Fluent API
이 게시물에서는 데이터 주석을 사용하여 엔터티 간의 관계를 만듭니다.
하나의 테이블로 데이터베이스 만들기
코드 첫 번째 접근 방식으로 데이터베이스에 Student라는 테이블을 만드는 것부터 시작하겠습니다. 도메인 클래스 Student 는 아래 목록과 같이 생성할 수 있습니다.
namespace CodeFirstDemoApp { public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } }
이미 눈치챘을 수도 있지만 Student 클래스는 일반 클래스입니다. Entity Framework는 Student 클래스를 사용하여 데이터베이스에 테이블을 만듭니다. Student 클래스는 도메인 엔터티를 나타내며 데이터베이스에 대한 정보나 참조가 없어야 합니다. Entity Framework는 Student 클래스를 사용하여 Student 테이블을 만듭니다.
도메인 엔터티 클래스가 만들어지면 다음으로 DataContext 클래스를 상속할 Context 클래스를 만들어야 합니다. 컨텍스트 클래스는 아래 목록과 같이 만들 수 있습니다.
using System.Data.Entity; namespace CodeFirstDemoApp { public class Context : DbContext { public Context() : base() { } public DbSet<Student> Students { get; set; } } }
기본 생성자를 사용하여 Context 클래스를 만들었습니다. 이 게시물의 뒷부분에서 생성자의 다양한 옵션에 대해 이야기 할 것입니다. 컨텍스트 클래스에서 다음 작업을 수행하고 있습니다.
- 기본 생성자를 만듭니다. 생성자에 매개 변수를 전달하지 않기 때문에 EF는 Namespace.Class name이라는 이름을 가진 데이터베이스를 만듭니다. 따라서 이 경우 생성된 데이터베이스 이름은 CodeFirstDemo.Context가 됩니다.
- Context 클래스의 생성자에 연결 문자열 정보를 전달하지 않기 때문에 EF는 SQL Server Express의 기본 데이터베이스 서버에 데이터베이스를 만듭니다.
- 원하는 이름으로 원하는 서버에 데이터베이스를 만들려면 연결 문자열을 만들고 Context 생성자에서 매개변수로 전달해야 합니다.
- 데이터베이스에 테이블을 만들려면 도메인 엔터티가 전달된 제네릭 DbSet 형식의 공용 속성을 만듭니다.
지금까지 Student 엔터티 클래스와 Context 클래스를 만들었습니다. 이제 간단한 LINQ to Entity 쿼리를 작성하여 데이터베이스를 만들고 아래 목록과 같이 작업을 수행할 수 있습니다.
using System; using System.Linq; namespace CodeFirstDemoApp { class Program { static void Main(string[] args) { CreateStudent(); Console.WriteLine("Student Created"); using (Context c = new Context()) { var result = from r in c.Students select r; foreach (var r in result) { Console.WriteLine(r.Name); } } Console.ReadKey(true); } static void CreateStudent() { Student s = new Student { Id = 1, Age = 12, Name = "Foo" }; using (Context c = new Context()) { c.Students.Add(s); c.SaveChanges(); } } } }
Custom Database Name
Context 클래스의 기본 생성자를 사용할 때 EF는 기본적으로 Namespace.Contextclass 이름으로 정규화된 이름을 사용하여 데이터베이스를 만듭니다. 그러나 아래 목록과 같이 생성자에서 이 경우 mydb 데이터베이스의 원하는 이름을 전달할 수 있습니다.
public Context() : base("mydb") {}
SQL Express에서 EF는 mydb라는 이름의 데이터베이스를 만듭니다.
연결 문자열 작업
현재로서는 EF를 사용하여 데이터베이스를 만들고 있습니다. 그러나 연결 문자열을 전달하여 원하는 서버에 데이터베이스와 이름을 만들 수 있습니다. 연결 문자열은 아래와 같이 구성 파일에서 만들 수 있습니다.
<connectionStrings> <add name="democonnectionstring" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=Demo1;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" /></connectionStrings>
로컬 db 서버에 데이터베이스를 생성하기 위해 연결 문자열을 만들었습니다. 다음으로 아래 목록과 같이 Context 클래스의 생성자에 연결 문자열 이름을 전달해야 합니다.
public Context() : base("name=democonnectionstring") {}
Relationship Between Entities
Code First 접근 방식에서는 다음 두 가지 옵션 중 하나를 사용하여 엔터티 간의 관계를 만들 수 있습니다.
- 데이터 주석
- Fluent API
이 게시물에서는 데이터 주석을 사용하여 관계를 만듭니다.
일대일 관계
두 엔터티 간에 일대일 관계를 만들어야 하는 요구 사항이 있을 수 있습니다. 즉, 두 엔터티 간의 기본 키 – 외래 키 관계가 필요합니다. 두 개의 엔터티와 다음 규칙이 있다고 가정해 보겠습니다.
- Student 및 StudentAccount라는 두 개의 엔터티가 있습니다
- 학생은 기본 엔터티입니다.
- StudentAccount는 Student에 종속된 엔터티입니다.
- StudentAccount의 기본 키는 Student의 외래 키가 됩니다.
학생 없이 StudentAccount를 만들 수 없어야 하며 StudentAccount에는 Student를 한 번만 입력할 수 있습니다. 간단히 말해서 각 학생은 하나의 StudentAccount를 가지며 학생 없이는 StudentAccount가 존재하지 않습니다.
먼저 기본 엔터티인 학생을 만들어 보겠습니다.
public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public virtual StudentAccount StudentAccount { get; set; } }
눈치채셨겠지만 Student 엔터티에는 아래 목록과 같이 생성된 StudentAccount 형식의 가상 속성이 있습니다.
public class StudentAccount { public int Id { get; set; } public string Name { get; set; } public int Amount { get; set; } [Required] public virtual Student Student { get; set; } }
다시 말하지만, StudentAccount 엔터티에 Student 형식의 가상 속성이 있다는 것을 알 수 있습니다. Student는 기본 엔터티이므로 StudentAccount 엔터티의 가상 Student 속성에 Required로 주석이 추가됩니다. 또한 아래 목록과 같이 Context 클래스를 만들 수 있습니다.
using System.Data.Entity; namespace CodeFirstDemoApp { public class Context : DbContext { public Context() : base("name=democonnectionstring") {} public DbSet<Student>Students { get; set; } public DbSet<StudentAccount>StudentAccounts { get; set; } } }
Student 테이블에 해당 행이 없으면 StudentAccounts 테이블에 행을 만들 수 없다는 점을 항상 기억하십시오. 아래 목록에 표시된 대로 관련 테이블에서 데이터를 생성할 수 있습니다.
static void CreateStudent() { Student s=new Student { Id=1, Age=12, Name="Foo" }; StudentAccount sa=new StudentAccount { Amount=300, Name="Sports Account", Student=s }; Context c=new Context(); c.Students.Add(s); c.StudentAccounts.Add(sa); c.SaveChanges(); }
눈치채셨겠지만 Student의 개체를 StudentAccount의 속성으로 설정하고 있습니다. 아래 목록에 표시된 대로 두 테이블 모두에서 레코드를 검색할 수 있습니다.
Context c=new Context(); var result=from r in c.Students select r; foreach (var r in result) { Console.WriteLine(r.Name); Console.WriteLine(r.StudentAccounts.Amount); }
SQL Server Management Studio에서 엔터티 간의 관계를 확인하기 위해 아래 이미지와 같이 제약 조건과 키로 생성된 열을 볼 수 있습니다.

여기서 StudentAccounts 테이블의 Id 열은 기본 키이자 외래 키입니다.
일대다 관계
두 엔터티 간에 너무 많은 관계를 생성해야 하는 요구 사항이 있을 수 있습니다. 두 개의 개체가 있다고 가정해 보겠습니다
- Student 및 StudentAddress의 두 가지 엔터티가 있습니다
- 학생은 기본 엔터티입니다.
- StudentAddress는 Student에 종속된 엔터티입니다.
- 한 명의 학생이 여러 StudentAddress에 등록할 수 있습니다.
한 명의 학생이 여러 개의 StudentAddress를 가질 수 있습니다. StudentAddress의 열 중 하나는 Student의 기본 키로 외래 키를 갖습니다.
먼저 기본 엔터티인 Student를 만들어 보겠습니다.
public class Student { public Student() { StudentAddresses=new HashSet<StudentAddress>(); } public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public ICollection<StudentAddress>StudentAddresses { get; set; } }
StudentAddress 컬렉션의 속성을 생성한 다음 Student의 생성자에서 StudentAddress 속성의 설정 값을 생성한다는 것을 눈치채셨을 것입니다. StudentAddress 클래스는 아래 목록과 같이 만들 수 있습니다.
public class StudentAddress { public int Id { get; set; } public string Address { get; set; } public int StudentId { get; set; } public virtual Student Student { get; set; } }
다시 말하지만, StudentAddress 엔터티에 Student 형식의 가상 속성이 있다는 것을 알 수 있습니다. Student는 기본 엔터티이므로 StudentAddress의 가상 Student 속성에는 해당 StudentId 속성이 있습니다.
또한 Context 클래스는 아래 목록과 같이 만들 수 있습니다.
public class Context : DbContext { public Context() : base("name=democonnectionstring") {} public DbSet<Student>Students { get; set; } public DbSet<StudentAddress>StudentAddresses { get; set; } }
Student 테이블에 해당 행이 없으면 StudentAddress 테이블에 행을 만들 수 없다는 점을 항상 기억하십시오. 아래 목록에 표시된 대로 관련 테이블에서 데이터를 생성할 수 있습니다.
static void CreateStudent() { Student s=new Student { Id=1, Age=12, Name="Foo" }; StudentAddress sa1=new StudentAddress { Address="Delhi", Id=1 }; StudentAddress sa2=new StudentAddress { Address="Bangalore", Id=2 }; s.StudentAddresses.Add(sa1); s.StudentAddresses.Add(sa2); Context c=new Context(); c.Students.Add(s); c.SaveChanges(); }
눈치채셨겠지만 StudentAddress의 개체를 Student에 추가하고 있습니다. 아래 목록과 같이 두 테이블에서 레코드를 검색할 수 있습니다.
static void Main(string[] args) { CreateStudent(); Console.WriteLine("Student Created"); Context c=new Context(); var result=from r in c.Students.Include("StudentAddresses") select r; foreach (var r in result) { Console.WriteLine(r.Name); foreach(var a in r.StudentAddresses) { Console.WriteLine(a.Address); } } Console.ReadKey(true); }
SQL Server Management Studio에서 엔터티 간의 관계를 확인하기 위해 아래 이미지와 같이 제약 조건과 키로 생성된 열을 볼 수 있습니다.

Many to Many Relationship
마지막으로 다대다 관계를 구성하는 방법을 살펴보겠습니다. Student 엔터티와 Subject 엔터티가 있다고 가정 해 보겠습니다. 한 명의 학생이 여러 과목에 등록할 수 있으며 한 과목에 많은 학생이 있을 수 있습니다. 이러한 엔터티 간에 너무 많은 관계를 만들려면 먼저 아래 목록과 같이 Student 엔터티를 만들어 보겠습니다.
public class Student { public Student() { Subjects=new HashSet<Subject>(); } public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public ICollection<Subject>Subjects { get; set; } }
여기서 우리는 Subjects 컬렉션의 속성을 만든 다음 Student의 생성자에서 Subjects 속성의 설정 값을 만듭니다. Subject 클래스는 아래 목록과 같이 만들 수 있습니다.
public class Subject { public Subject() { Students=new HashSet<Student>(); } public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Student>Students { get; set; } }
Subject 클래스에서도 Students 컬렉션의 속성을 만들고 Subject 클래스의 생성자에서 학생 집합을 만듭니다. 이것이 엔티티 간에 너무 많은 관계를 만들기 위해 해야 할 전부입니다.
또한 Context 클래스는 아래 목록과 같이 만들 수 있습니다.
public class Context : DbContext { public Context() : base("name=democonnectionstring") {} public DbSet<Student>Students { get; set; } public DbSet<Subject>Subjects { get; set; } }
아래 목록과 같이 Students and Subjects 테이블에 행을 만들 수 있습니다.
static void CreateStudent() { Student s=new Student { Id=1, Age=12, Name="Foo" }; Subject s1=new Subject { Id=1, Name="Phy" }; Subject s2=new Subject { Id=2, Name="Maths" }; s.Subjects.Add(s1); s.Subjects.Add(s2); Context c=new Context(); c.Students.Add(s); c.SaveChanges(); }
다음과 같이 두 테이블에서 레코드를 검색할 수 있습니다.
static void Main(string[] args) { CreateStudent(); Console.WriteLine("Student Created"); Context c=new Context(); var result=from r in c.Students.Include("Subjects") select r; foreach (var r in result) { Console.WriteLine(r.Name); foreach(var a in r.Subjects) { Console.WriteLine(a.Name); } } Console.ReadKey(true); }
Student 엔터티와 Subject 엔터티 간의 관계를 확인할 때 EF가 다대다 관계를 유지하기 위해 추가 테이블을 만들었음을 알 수 있습니다

이것이 Code First 접근 방식에서 엔터티 간의 관계를 만드는 방법입니다. 이 게시물에서는 단일 엔터티로 작업을 시작한 다음 엔터티 간의 관계를 만드는 것으로 진행했습니다. 이 게시물이 도움이 되었기를 바라며 읽어 주셔서 감사합니다.
Infragistics Ultimate 15.2가 나왔습니다.다운로드하여그 힘을 실제로 확인하십시오!
