네비게이션 프로퍼티

냐옹·2024년 4월 9일
0

.NET

목록 보기
2/31

네비게이션 프로퍼티

네비게이션 프로퍼티는 Entity Framework 에서 엔티티 간의 관계를 나타내는 프로퍼티이다. 이를 통해서 연관된 엔티티들 간에 탐색할 수 있으며, 코드 내에서 마치 객체 간의 관계를 다루듯 데이터베이스 테이블 간의 관계를 다룰 수 있다.
역할

  • 엔티티간 탐색( 제일 중요 )
     CF) include() : 사실상 JOIN 과 같다.
     어떤 엔티티에 들어간 네비게이션 프로퍼티를 통해서 해당 엔티티에 속한 모든 엔티티에 쉽게 접근할 수 있다.
  • 관계의 표현
     엔티티 간의 관계를 코드 상에서 직관적으로 표현할 수 있어서, 객체 지향적이 방식으로 관계형 데이터를 다룰 수 있다.
  • 쿼리의 간결성
     결국에 조인 대신에 Include를 쓰기 위해서 네비게이션 프로퍼티를 만드는 것이어따.....
    var blogsWithPosts = context.Blogs.Include(blog => blog.Posts).ToList()
    결국에 사실상 include가 조인의 역할을 수행하는 것과 마찬가지이다.
    using Microsoft.EntityFrameworkCore;

var blogWithPostsAndComments = context.Blogs
.Where(b => b.BlogId == 1)
.Include(b => b.Posts)
.ThenInclude(p => p.Comments)
.FirstOrDefault();
이고 여기서 Blog와 Post는 1:n Post와 Comment도 1:n 관계이다.
따라서 include를 이용한 쿼리 작성 시에는 위에서부터 순차적으로 넘어온다.
결과로서 나오는 것은 Blog 엔티티의 인스턴스이다. 그래서 우리는 네비게이션 프로퍼티를 추가했던 것이었고
이제 그 안에서 LINQ를 쓰면 알맞게 딱 떨어진다.

Include를 쓰는 것보다는 사용자 정의타입을 혼용하는게 나을 수도 있다.
예를 들어서
var blogWithPostsAndComments = context.Blogs
.Where(b => b.BlogId == 1)
.Include(b => b.Posts)
.ThenInclude(p => p.Comments)
.FirstOrDefault();
위에서 보았던 이런 코드가 있다고 쳐보자.

근데 이런 경우에 만약에 Post안의 요소 중에 모든 것이 Null 이 아니라고 한다면은 괜찮겠지만, 순회를 해야하는 입장에서 순회 전에는 안에 무엇이 들었는지 모르지 않는가. 그래서 컴파일러는 빌드 전에 이것을 미리 경고한다. 물론 빌드는 되긴하지만 런타임에러가 솔직히 더 무섭다. 따라서 이렇게 사용할 수 있다.

var blogWithPostAndComments = context.Blogs
.Where( b=>b.BlogId == 1)
.Select( x=> new {
// 사용자 정의 타입을 만들어서 귀찮더라도 그렇게 주는 것이 마음도 편하고 좋다.
// 그리고 NULL 방지 로직은 본인이 만들어야 한다.
})
. ........~

JS의 익명함수 그리고 C#의 대리자를 통한 익명함수(람다) 참조
자바스크립트의 익명함수를 최대한 비슷하게 쓰려면 어떻게 해야할까. 예를 들어서 JS에 이런코드가 있다고 쳐보자.
const fun1 = (a) => { console.log(a) }
이걸 갖다가 C#에서 표현하려면 대리자를 사용해야한다.
Action Fun1= (a) => { Console.WriteLine(a); }

람다를 잘 알아야 한다. 마이크로소프트 문서를 보니까 LINQ를 적극 사용했다가 요즘 문서를 보면 전부 람다로 적혀있다. 근데 람다식은 그렇더라도 람다문을 알아가다보면 대리자라는 것이 등장한다. 그래서 문서를 잘 읽기 위해서는 대리자에 대한 이해가 필요하다.
대리자를 여러 책에서 써놓은 것을 보니까 이해하기가 좀 그랬는데, 결국 보면 대리자는 메서드에 대한 참조를 표현하는 타입이다. 대리자를 사용하면 메서드를 변수에 할당하고, 매개변수로 전달하고 다른 메서드의 반환값으로 사용할 수 있다. 그렇기 때문에 프로그램에서 콜백 함수와 이벤트 핸들러를 대리자로 구현할 수 있는 것이다.

원래 대리자의 선언 키워드는 delegate이다. 아래에서 설명하는 것들은 ‘내장된’ 대리자이다. 내장된 대리자들은 개발자가 특정 시그니쳐를 가진 메서드를 참조할때 매번 새로운 대리자 타입을 정의하지 않아도 되게 해준다. 가장 자주 사용되는 내장 대리자 타입은 Action, Func이다.
자주 사용되는 내장 대리자 타입은 기본적으로 2개가 있고, 이벤트 처리를 위한 것이 1개가 있다. ( Func 대리자 / Action 대리자, EventHandler )
1. Func 대리자.
A. Func 대리자는 반환값이 있는 메서드를 참조하기 위해서 사용된다.
B. Func은 0개에서 16개 까지의 매개변수를 가질 수 있고 마지막 타입 파라미터는 메서드의 반환 타입을 나타낸다.
예시코드
Func<int, int, int> add = ( x, y ) => x + y;
int result = add( 1, 2 );

  1. Action 대리자
    A. Action대리자는 반환값이 없는 메서드를 참조하기 위해서 사용한다.
    B. 마찬가지로 0~16개의 매개변수를 가질 수 있다.
    Action greet = (name) => { Console.Write(“dd”);
    C. Action에 매개변수의 타입을 전달해주어야 한다.
    D. 그리고 람다 관련 규칙은 자바스크립트와 거의 같다.
    i. 인수가 한개일때 괄호를 생략한다던지.. 그런거

  2. 하나 추가로 Predicate대리자
    A. Predicate 대리자는 하나의 매개변수를 받고 bool값을 반환하는 메서드를 참조하기 위해 사용된다. 주로 조건 검사 또는 특정 조건에 대한 판단을 수행할 때 사용된다.
    B. bool Predicate
    C. Predicate isPositive = x => x>0;

  3. EventHandler 대리자
    A. EventHandler와 EventHandler는 이벤트에 대한 추가정보를 제공하는 EventArgs 파생 클래스의 인스턴스를 매개변수로 사용할 수 있다.
    B. 람다 자체와 관련은 없는듯..?
    public event EventHandler MyEvent;

protected virtual void OnMyEvent(MyEventArgs e){
MyEvent?.Invoke( this, e );
}
1, 2번은 이해가 잘되는데 3번이 이해가 잘 안된다. 그래서 조금 더 알아보았다. 다음페이지를 보자.

0개의 댓글