2012-12-19 4 views
7

우리는 클라이언트 (프레젠테이션)와 서버 (데이터/비즈니스 계층)간에 WCF를 사용하여 N 계층 아키텍처 응용 프로그램을 개발하고 있습니다. 솔직히 말해서 WCF를 통해 효율적으로 계산 된 데이터를 노출하는 방법에 대한 실제 예/정보를 찾을 수 없습니다.WCF를 통해 개체의 계산 된 데이터를 노출하는 방법

내 문제를 설명하기 위해 우리는 많은 거래를하는 ATM 기계를 가지고있다. 그래서 우리는 ATM 클래스와 트랜잭션 클래스 사이에 1-N 관계를 가지고 있습니다. ATM 클래스에는 Location, ModelNo, Description, InstallDate와 같은 속성이 있으며 트랜잭션 레코드에는 Amount, DateTime, CustomerInfo, TicketPaperLength, Electricity와 같은 정보가 있습니다.

WCF를 통해 이러한 클래스를 노출하는 것은 문제가되지 않습니다. 문제는 기본 Transaction 테이블을 기반으로 ATM에 대해 계산 된 필드가 많이 있다는 것입니다. 예를 들어 클라이언트 응용 프로그램은 계산 된 ATM 데이터를 기반으로 보고서를 사용합니다. ATM의 계산 된 데이터의 예로는 AverageTicketPaperLength, AverageAmount, DeviationAmount, AverageElectricity 등이 있습니다. 이러한 계산 된 데이터가 많이 있습니다. 계산은 클라이언트 측이 아니라 서버에서 수행해야합니다. 이 보고서 정의가 모두 수정 되었다면 큰 문제는 아니 었습니다. 우리는 보고서를 위해 별도의 서비스/Poco를 만들 수있었습니다. 비즈니스 계층에 계산을 넣고 필요에 따라 Poco를 채 웁니다. 그러나 클라이언트 응용 프로그램에는 ATM의 계산 된 특성 세트에서 보고서를 필터링하고 데이터로 다른 (계산 된) 특성 세트를 리턴 할 수있는 기능이 있어야합니다.

계산 된 속성이 약 500 개인 Poco를 만들 수 있습니다. 각 보고서에는 10 개의 속성 만 사용됩니다. 물론 우리는 모든 엔티티에 대해 매번 500 개의 계산을 실행하는 것을 원하지 않습니다.

그래서 일반적으로 어떻게 개체의 계산 된 데이터를 노출하는지 궁금합니다. WCF. Entity Framework, Poco 및 WCF를 설명하는 거의 모든 예제는 엔티티의 지속적인 필드 만 처리하며 이는 매우 간단합니다.

답변

7

WCF를 통해 엔터티를 노출시키지 마십시오. 일부 DTO를 만듭니다.

: WCF 층에서

-

DtoInfoForReport1 GetInfoForReport1(long atmId) { ... call BL here... } 
DtoInfoForReport2 GetInfoForReport2(long atmId) { ... call BL here... } 

데이터 영역에서 -

AtmEntity 
{ 
    long Id {get;set;} 
    ... some properties ... 
    HashSet<Transaction> AtmTransactions {get;set;} 
} 

전송 객체 - BL에

DtoInfoForReport1 
{ 
    long AtmId {get;set;} 
    XXX SomeCalculatedValue {get;set;} 
} 

-

DtoInfoForReport1 CreateInfoForReport1(long atmId) 
{ 
    var atm = YYY.GetEntity<AtmEntity>(atmId); 
    return new DtoInfoForReport1 
    { 
    AtmId = atmId, 
    SomeCalculatedValue = DoSomeCalculationOverMyAtmWithItsTransactions(atm), 
    }; 
} 

희망 사항. 그렇지 않으면 주석. 의견에 따라

편집 : 이 같은 DTO들을 제안보다 :

[DataContract] 
public DtoRequestedCalculations 
{ 
    [DataMember] 
    public long AtmId {get;set;} 

    [DataMember] 
    public List<DtoRequestedCalculationEntry> Calculations {get;set;} 
} 

[DataContract] 
public DtoRequestedCalculationEntry 
{ 
    [DataMember] 
    public string/long/Guid/XXX ParameterIdentifier {get;set;} 

    [DataMember] 
    public double/ DtoParameterCalculatedValueBase {get;set;} 
} 

은 이제 항상 배가되는 계산 된 값이 기본적으로 이루어집니다 경우. DtoParameterCalculatedValueBase, STH이 같다 - 당신의 가치가 있거나 다른 종류의 수 있습니다 경우에 당신은 몇 가지 기본 클래스가 필요합니다 :

[DataContract] 
[KnownType(typeof(DtoParameterDoubleCalculatedValue))] 
[KnownType(typeof(DtoParameterXXXCalculatedValue))] 
public DtoParameterCalculatedValueBase 
{ 
    ...whatever common part there may be or nth... 
} 

public DtoParameterDoubleCalculatedValue : DtoParameterCalculatedValueBase 
{ 
    [DataMember] 
    public double Value {get;set;} 
} 

public DtoParameterXXXCalculatedValue : DtoParameterCalculatedValueBase 
{ 
    [DataMember] 
    public XXX Value {get;set;} 
} 

참고 KnownType 속성을 -이 유형은 기본 클래스의 자리에 올 수 있습니다 무엇을 WCF를 알려줍니다.상속 된 각 유형에 대해이 특성을 제공해야합니다 (또는 이미 다른 이야기 인 DataContractResolver를 사용하십시오). WCF에서보다

: 일반적으로

DtoRequestedCalculations GetCalculatedValuesForAtm(long atmId, List<long/string/ Guid/XXX> valueIdentifiers); 
+0

나는 DTO의를 사용하여 동의합니다. 당신의 설명이 제 문제를 꽤 지적합니다. 문제는 내가 예를 들어에 대한 정확한 정의를 모른다는 것입니다. 포어 핸드에서 GetInfoForReport1 및 GetInfoForReport2. 다른 보고서도있을 수 있으며 사용자가 요청한 데이터를 알지 못합니다. 최종 사용자는 ATM에서 일부 계산 된 필드를 선택하고 보고서를 요청합니다. 가능한 각 필드 조합에 대해 DTO를 작성하는 것은 너무 많습니다. – Erik

+0

대답이 –

+0

으로 변경되었습니다. 그런 다음 WCF GetCalculatedValuesForAtm을 사용하면 valueIdentifiers가 해당 계산을 참조합니다. 그러나 여전히 AverageElectricity가 높은 ATM 목록을 원한다면 모든 ATM을 반복해야하고 각 ATM의 AverageElectricity에 대해이 WCF를 호출해야합니다. (단지 1 ATM의 보고서 대신 모든 ATM의 보고서를 의미한다는 것을 깨달았습니다. 원래 질문에서는 언급되지 않았습니다.) – Erik

관련 문제