How to set object settlement data through WCF

We developed an N-tier architecture application using WCF between the client (presentation) and the server (data / business tier). Honestly, I cannot find any real examples / information on how to expose efficiently calculated data through WCF.

To describe my problem, we say that we have ATMs that have many transactions. Thus, we have a 1-N relationship between the ATM class and the transaction class. The ATM class has properties such as Location, ModelNo, Description, InstallDate, and transaction records such as Amount, DateTime, CustomerInfo, TicketPaperLength, ElectricityUsed

Providing these classes through WCF is not a problem. The problem is that we have many calculated fields for ATM, which are based on a base transaction table. For example, a client application uses reports based on calculated ATM data. Examples of ATM settlement data can be: AverageTicketPaperLength, AverageAmount, DeviationAmount, AverageElectricity, etc. Etc. There are many, many of these estimates. Settlements should be made on the server, not on the client side. If these report definitions were fixed, this would not be a big problem: we could create separate services / Pocos for reports. Put the calculations in the business layer and fill out Poco as needed. But the client application should be able to filter reports for any set of calculated ATM properties and return another set of (calculated) properties as data.

I could create a Poco with approximately 500 calculated properties, where for each individual report only 10 properties can be used. But, of course, we do not want all 500 calculations to be performed each time for each object.

So, in general, I wonder how you can set the calculated data of the object through, for example, WCF. Almost all the examples I see explaining that the Entity Framework, Poco, and WCF deal only with the constant fields of an object, and this is pretty straight forward.

+7
source share
1 answer

Do not expose objects through WCF, create some DTOs.

For example:

In the wcf layer -

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

In the data layer -

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

Object Transfer -

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

In BL -

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

I hope I understood your question correctly. Otherwise a comment.

Edit based on comment: Than I suggest DTO as follows:

 [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;} } 

Now, if your calculated value is always doubled, it basically runs. If your values ​​can be or different, you will need a base class - DtoParameterCalculatedValueBase, which looks like this:

 [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;} } 

Pay attention to the KnownType attribute - it tells WCF what types can appear instead of the base class. You will need to provide this attribute for each inherited type (or use a DataContractResolver, which is already a different story).

Than in WCF:

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

All Articles