2011-03-21 3 views
1

Model 클래스의 DataAnnotation 특성을 사용하여 유효성 검사를 수행하고 있으며, Model 클래스는 응용 프로그램의 클라이언트 및 서버 쪽에서 유효성 검사에 사용됩니다.순환 참조를 발생시키지 않고 LazyLoading을 WCF와 함께 사용하려면 어떻게해야합니까?

내 문제는 내가 어떻게 게으른로드 내 모델의 속성을 순환 참조를 포함

라이브러리를 유발하지 않고 알아낼 수 없습니다 것은 다음과 같습니다

  • WCF 서비스 라이브러리
  • 클라이언트 측 DATAACCESS 도서관 도서관
  • 모델

모델 천칭 자리 때문에 데이터 유효성 검사를 위해 클라이언트 측과 서버 측에서 모두 사용됩니다. 모델 라이브러리 내에서 DataAccess 라이브러리를 참조 할 수 없습니다. 따라서, 어떻게 게으른 로딩을 설정할 수 있습니까?

예를 들어, 나는 게으른로드되어야 PhoneNumbers의 속성을 가진 ConsumerModel 있습니다. Client-Side DAL을 참조하지 않고 ConsumerModel 내에서 PhoneNumberModels를로드하려면 어떻게해야합니까?

클라이언트 측 DAL :

using MyModels; 

public class ConsumerDataAccess 
{ 
    public ConsumerModel GetConsumerById(int id) 
    { 
     ConsumerDTO dto = WCFService.GetConsumer(id); 
     return new ConsumerModel(dto); 
    } 
} 

ConsumerModel :

public class ConsumerModel 
{ 
    public ObservableCollection<PhoneNumberModel> _phoneNumbers; 

    public ObservableCollection<PhoneNumberModel> PhoneNumbers 
    { 
     get 
     { 
      if (_phoneNumbers == null) 
      { 
       // Can't reference DataAccess Library since that would cause a Circular Reference 
      } 
     } 
    } 
} 

나는이 구조 작업을 할 수있는 몇 가지 다른 방법은 무엇입니까?

나는 모델에 대한 유효성 확인을 유지하고 유효성 검사를 위해 클라이언트 및 서버 측의 모델을 사용하는 것을 선호합니다. 나는 또한 유효성 검사를 위해 DataAnnotation을 계속 사용하는 것을 선호한다.

편집

사람이 관심이 있다면 여기에 로렌스 Wenham의 답변에 따라 내 최종 솔루션입니다. 나는 이벤트 대신 델리게이트를 사용했다.

DAL :

public class ConsumerDataAccess 
{ 
    public ConsumerModel GetConsumerById(int id) 
    { 
     ConsumerDTO dto = WCFService.GetConsumer(id); 
     ConsumerModel rtnValue = new ConsumerModel(dto); 
     ConsumerModel.LazyLoadData = LazyLoadConsumerData; 
     return rtnValue; 
    } 
} 

private object LazyLoadConsumerData(string key, object args) 
{ 
    switch (key) 
    { 
     case "Phones": 
      return PhoneDataAccess.GetByConsumerId((int)args); 
     default: 
      return null; 
    } 
} 

모델 라이브러리 :

public class ConsumerModel 
{ 
    public delegate object LazyLoadDataDelegate(string id, object args); 
    public LazyLoadDataDelegate LazyLoadData { get; set; } 

    public ObservableCollection<PhoneNumberModel> _phoneNumbers; 

    public ObservableCollection<PhoneNumberModel> PhoneNumbers 
    { 
     get 
     { 
      if (_phoneNumbers == null && LazyLoadData != null) 
      { 
       _phoneNumbers = (ObservableCollection<PhoneNumberModel>) 
         LazyLoadData("Phones", ConsumerId); 
      } 
      return _phoneNumbers; 
     } 
    } 
} 

답변

2

한 가지 방법은 당신의 모델 클래스 속성의 get {}에 이벤트를 발생하는 다음에 게으른 로딩 관리를 구현할 수 귀하의 DAL에 대한 참조가있는 클라이언트 측. EG : 당신의 모델 클래스에서 다음

public class LazyLoadEventArgs: EventArgs 
{ 
    public object Data { get; set; } 

    public string PropertyName { get; set; } 

    public int Key { get; set; } 
} 

:

public event EventHandler<LazyLoadEventArgs> LazyLoadData; 

public ObservableCollection<PhoneNumberModel> PhoneNumbers 
{ 
    get 
    { 
     if (_phoneNumbers == null) 
     { 
      LazyLoadEventArgs args = new LazyLoadEventArgs { 
       PropertyName = "PhoneNumbers", 
       Key = this.Id 
      }; 
      LazyLoadData(this, args); 
      if (args.Data != null) 
       this._phoneNumbers = args.Data as ObservableCollection<PhoneNumberModel>; 
     } 
     return _phoneNumbers; 
    } 
} 

.Data 특성에 저장 한 후, 클라이언트 측의 DAL에서 데이터를 가져 오는의 일을했을 LazyLoadData 이벤트 핸들러 LazyLoadEventArgs. 예 :

private void Model_HandleLazyLoadData(object sender, LazyLoadEventArgs e) 
{ 
    switch (e.PropertyName) 
    { 
     case "PhoneNumbers": 
      e.Data = DAL.LoadPhoneNumbers(e.Key); 
      break; 
     ... 
    } 
} 
+0

나는 실제로 전화 번호 정보를로드하기 위해 DAL을 호출하는 것이 무엇인지를 잘 모르겠다. – Rachel

+0

수정 된 답변보기 LazyLoadData의 이벤트 핸들러는 DAL을 호출하는 것입니다. 로드 할 데이터를 식별하는 가장 좋은 방법을 찾아야합니다. 나의 예제에서 나는 어떤 종류의 문자열과 'Key'를 사용했다.하지만 열거 형을 사용할 수 있고, if (sender가 ConsumerModel)와 같은 것들과 결합 할 수있다. 모델에서 DAL을 유지합니다. –

+0

그래도 순환 참조 문제가 발생하지 않습니까? 모델은 Observers 라이브러리에 대해 알아야하며, Observers는 모델 라이브러리에 대해 알아야합니다. 내 원래의 문제는 모델 라이브러리에서 DAL을 참조 할 수 없다는 것입니다. 그래서이 둘을 결합 할 수 없습니다. – Rachel

0

WCF에서 "지연로드"를 사용하지 마십시오. 네트워크 통신은 시간이 많이 소요됩니다.PhoneNumbers을 사용하려는 경우 전화 번호로 Customer을 반환하는 방법을 제공해야합니다. 다른 접근 방식은 Expand 방법으로 열망하는로드를 정의 할 수있는 클라이언트 쪽 linq 쿼리를 제공하는 WCF Data Services을 사용합니다.

서비스 요청을 최소로 줄여야합니다.

질문을 다시 읽은 후 서비스와 클라이언트간에 모델을 공유하는 이유를 모르겠습니다. 모델은 엄격한 클라이언트 기능입니다. 유일한 공유 부분은 DTO이어야합니다.

+0

PhoneNumbers는 간단한 예였습니다. 대부분의 경우 문서는 큰 파일이므로 모든 상황에서 문서를 검색하지 않으려는 더 나은 예제가 문서 일 수 있습니다. 사용자는 자신의 UI를 사용자 정의 할 수 있으므로 화면에 Documents 섹션이있는 사용자는 문서를로드해야하고 다른 사용자는로드하지 않아야합니다. – Rachel

+0

다른 모델과 데이터 검색 방법이 다른 여러보기가 마음에 듭니다. –

+0

데이터의 각 섹션마다 다른보기가 있습니다. 사용자는 작업해야하는 정보에 따라 패널을 화면에 드래그/드롭 할 수 있습니다. 거의 모든 경우에 패널에는 소비자와 관련된 정보가 들어 있습니다. 소비자가로드 할 때 화면에있는 패널을 기반으로 화면에있는 정보 만로드해야합니다. – Rachel

관련 문제