Entity Framework 데이터 모델링 (1)
ET Core 간단하게 알아보기
데이터 모델링은 3가지 방법으로 가능하다.
-Convention(관례)
-Data Annotation(데이터 주석)
-Fluent API(직접 정의)
1. 관례의 경우에는 Id나 [클래스]Id가 붙을 경우 자동적으로 priamry key로 인식이 된다.
2. Attribute 즉, 속성을 활용하여 가능하다.
ex)
public int Id{ {get; set;}
[MaxLength(32)]
public string UserName {get; set;}
3. API를 사용하여 직접정의한다.
protected overrid void OnModelCreationg(ModelBuilder builder)
{
builder.Entity<GameResult>().Properity(x => x.UserName).ISUnicode(false);
}
지금까지는 1번 즉 관례의 방식으로 데이터 모델링을 사용했으나
2번과 3번도 유용하게 사용되는 경우가 있기에 모든 경우에 대하여 간단하게 알아보고자 한다.
[1]Entity Class에 대한 관례
정의) EF가 참조하는 클래스를 Entity Class라고 한다.
관례)
-public
-static이면 안됨
-생성자가 없거나, 인자 없는 생성자가 있어야 함
-id혹은 [클래스]id 형태의 property를 테이블의 Primary Key로 간주한다.
Column에 대한 관례
관례)
-property의 이름이 테이블 컴럼 이릅으로 사용
-propery의 타입을 해당하는 SQL타입으로 변환
-C# 형식의 기본 nullable이 테이블 컬럼 nullable에 영향
[2]Data Annotation
Blazor의 Form 검증 때 사용한 모든 Annotation이 모두 해당한다.
ex) Required, MaxLength...
[3] FLUENT API
Convention이나 Data Annotation으로 할 수 없는 모든 경우
Fluent Api로 처리가 가능하다.
ex)
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<GameResult>().Property(x => x.UserName).IsUnicode(false);
//UserId를 Index로 추가하는 코드 Has라 헷갈릴수 있지만 추가하는 코드이다.
builder.Entity<GameResult>().HasIndex(x => x.UserId);
//Score가 1000을 넘는 경우에만 필터링을 처리해서 추출하는 코드
builder.Entity<GameResult>().HasQueryFilter(p => p.Score > 1000);
}
이번엔 DB에서 특정 부분만을 제거해도록 하겠다.
Data Annotation에서는 [NotMapped] 속성을 사용하면 된다.
이를 만약에 class에다가 사용할 경우 DB생성에서 제외가 된다.
그리고 Fluent Api에서 사용할 경우
builder.Entity<GameResult>().Ignore(g => g.Excluded);
를 사용하면 된다.
다음으로 DB의 칼럼에서 TYPE과 SIZE 그리고 NULL여부를 제어하고 싶은 경우를 알아보겠다.
[Data Annotation의 경우]
Not null => [Required]
Set String Size => [MaxLength(123)]
Set String VarChar => X
[Fluent Api의 경우]
Not null => .IsRequired();
Set String Size => .HasMaxLength(123)
Set String Varchar => .IsUnicode(false)
테이블의 Primary Key를 설정하는 방식을 알아보겠다.
이 경우에는 위의 3가지 방식이 모두 가능하다.
[관례의 경우]
property의 이름에 Id가 들어가 있으면 기본 키로 인식해준다.
[속성의 경우]
[Key] 속성 값을 프로퍼티위에 붙여준다.
만약 [Key]의 값이 2개 이상의 프로퍼티에 지정되어 있는 복합 키라면
복합 키로 사용되므로 [Column(Order =0)]의 속성을 붙여서
순서를 지정해준다.
[Api의 경우]
.HasKey()로 지정해준다.
다음으로 테이블의 Index를 설정하는 경우는
Fluent Api만 가능하다.
builder.Entity<GameResult>().HasIndex(x => x.UserId);
그리고 테이블의 이름을 설정하는 것은 관례,속성,Api 모든 경우가 가능하다.
[관례]
public DbSet<GameResult> GameResults { get; set: }
[속성]
[Table("GameResultTable")] 을 class위에 붙여준다.
[Api]
builder.Entity<GameResult>().ToTable("GameResultTable");
마지막으로 결론을 정리해보자면
1)기본 상태로 충분하다면 관례방식으로
2)속성으로 가능하다면, 속성방식을 무조건 사용하자!
속성은 낮우에 Blazor Form Validation등 다른 곳에서도 재사용이 가능하기 때문이다.
3)위의 2가지 경우가 안되는 정말 절망적인 상황이라면 Fluent Api를 사용하자!
ex) Index관련...