2013-04-17 3 views
18

대부분의 Entity Framework POCO에는 가상 기능이 있습니다 (전부는 아니지만). 엔티티가 지연로드 될 수 있도록 이러한 함수가 가상이어야합니다.생성자에서 가상 함수를 호출하는 것을 피하려면 어떻게해야합니까?

생성자에서 Accommodations을 초기화하면 생성자에서 가상 함수가 호출됩니다. 이는 나쁜 습관입니다.

그러나 생성자가 아닌 경우 Accommodations을 어떻게 초기화 할 수 있습니까?

public class Venue 
{ 
    public Venue() 
    { 
     Accommodations = new HashSet<Accommodation>(); 
    } 

    public virtual ICollection<Accommodation> Accommodations { get; set; } 
} 
+1

지연로드의 점까지, 모두를 초기화하는 _not_입니다 처음 사용. –

+0

@JohnWillemse 만약 내가 그것을 null로 내보기에서 null 예외가 나타납니다. –

+0

아니요, null을 테스트하고 필요할 때 초기화합니다. 사용법에 대한 설명은 아래 Willem Duncan의 대답을 참조하십시오. 어쩌면 같은 대답에 대한 Daniel의 의견에 따라 다른 패턴을 혼동하는 것일 수도 있습니다. –

답변

12
public class Venue 
{ 
    private accommodations_ = new HashSet<Accommodation>(); 

    public Venue() { } 

    public virtual ICollection<Accommodation> Accommodations 
    { 
     get { return accommodations_; } 
     set { accommodations_ = value; } 
    } 
} 
+3

이상한 명명 규칙은 무엇입니까? 일반적으로 밑줄을 앞에 둡니다. –

+1

@DanielHilgarth, 나는 그것을 전혀 관례라고 부르지 않을 것이다. 내가 정말로 바꿀 필요가있는 (아마도 나쁜) 습관이다. –

+0

EF는 맨 앞의 밑줄을 그다지 좋아하지 않는다. – Casey

2

지연로드, 당신은 심지어 처음 액세스 년대 Accommodations 전까지 초기화, 그래서 null을 두지 마십시오.

이를 automaticly 자체를 초기화하기 위해 다음과 같이 래핑 할 수

:

private ICollection<Accommodation> _accommodations; 

public virtual ICollection<Accommodation> Accommodations { 
    get { 
     if (_accommodations == null) 
     { 
      // Initialize or load data here. 
      _accommodations = new HashSet<Accommodation>(); 
     } 
     return _accomodations; 
    } 
    set { 
     _accommodations = value; 
    } 
} 

이 솔루션에 대한 아래의 설명을 읽어 보시기 바랍니다!

+7

그는 ORM의 맥락에서 게으른 로딩에 대해 이야기하고 있습니다. ORM이이 모든 작업을 처리하므로 답변이 그 요점을 놓칩니다. 또한 여기에 표시되는 연습과 관련하여 [이 답변] (http://stackoverflow.com/questions/14774008/good-or-bad-practice-initializing-objects-in-getter/14774042#14774042)을 참조하십시오. –

+0

좋은 지적, 매일 무언가를 배우고 답변에 대한 포인터를 추가했습니다. –

+0

Daniel 링크를 이용해 주셔서 감사합니다. –

14

또 다른 옵션은 설정자를 비공개로 표시하는 것입니다. 이렇게하면 생성자에서 가상 멤버를 호출하는 문제가 해결됩니다.

일단 그렇게하면 발신자 (EF 제외)가 디자인에서 필요에 따라 해당 속성을 설정할 수있는 방법을 제공해야합니다. 오버로드 된 생성자를 사용하여 숙박 시설 목록을 전달하거나 선택적으로 컬렉션 (도메인 중심 디자인)을 캡슐화하고 항목을 추가/제거하는 방법을 사용할 수 있습니다 (EF에서는 완전 캡슐화에 대한 지원이 부족하여 "hackish"가 됨). 자 NHibernate와 달리 컬렉션)은 C# 6.0 기본 초기화와

public class Venue 
{ 
    public Venue() 
    { 
     Accommodations = new HashSet<Accommodation>(); 
    } 

    public Venue(ICollection<Accommodation> accommodations) 
    { 
     Accommodations = new List<Accommodation>(accommodations); 
    } 

    public virtual ICollection<Accommodation> Accommodations { get; private set; } 
} 
+2

정확히 내가 필요한 것. 이 질문이 1 년이 넘은 것은 얼마나 재미 있었는지, 아직이 답변을 게시하기 불과 4 시간 전입니다. – Xcelled194

0

가 private 변수를 사용하지 않고 간단하게 할 수있다 :

public class Venue 
{ 
    public virtual ICollection<Accommodation> Accommodations {get; set; } = new HashSet<Accommodation>(); 
} 
관련 문제