【问题标题】:How to expose calculated data of an entity through WCF如何通过 WCF 公开实体的计算数据
【发布时间】:2012-12-06 18:00:18
【问题描述】:

我们正在客户端(表示)和服务器(数据/业务层)之间使用 WCF 开发 N 层架构应用程序。老实说,我找不到任何关于如何通过 WCF 公开有效计算数据的真实示例/信息。

为了描述我的问题,说我们的 ATM 机有很多交易。所以我们在 ATM 类和事务类之间存在 1-N 关系。 ATM 类具有 Location、ModelNo、Description、InstallDate 等属性,交易记录具有 Amount、DateTime、CustomerInfo、TicketPaperLength、ElectricityUsed 等信息

通过 WCF 公开这些类不是问题。问题是我们有很多基于底层交易表的 ATM 计算字段。例如,客户端应用程序使用基于 ATM 计算数据的报告。 ATM 的计算数据示例可能是:AverageTicketPaperLength、AverageAmount、DeviationAmount、AverageElectricity 等。这些计算数据有很多很多。计算应该在服务器而不是客户端进行。如果这些报告定义都被修复,那么问题就不会那么大了:我们可以为报告创建单独的服务/Poco。将计算放入业务层并根据需要填充 Poco。但是客户端应用程序必须能够根据 ATM 的任何计算属性集过滤报告,并将另一组(计算的)属性作为数据返回。

我可以创建一个包含大约 500 个计算属性的 Poco,其中每个报告可能仅使用 10 个属性。但我们当然不希望每次都为每个实体执行所有 500 次计算。

所以总的来说,我想知道如何通过例如公开实体的计算数据。 WCF。我看到的几乎所有解释实体框架、Poco 和 WCF 的示例都只处理实体的持久字段,这非常简单。

【问题讨论】:

    标签: c# wcf poco


    【解决方案1】:

    不要通过 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;}
    }
    

    传输对象 -

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

    在 BL 中 -

    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,它是这样的:

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

    【讨论】:

    • 总的来说,我同意使用 DTO。你的解释很好地指出了我的问题。问题是我不知道例如的确切定义。正手GetInfoForReport1 和GetInfoForReport2。可能还有其他报告,我不知道用户要求哪些数据。最终用户从 ATM 中选择一些计算字段并请求报告。为每个可能的字段组合创建一个 DTO 有点过分
    • 好的,那么使用 WCF GetCalculatedValuesForAtm 的想法是 valueIdentifiers 指的是相应的计算?但这仍然需要,如果您想要一个具有高 AverageElectricity 的 ATM 列表,则必须遍历所有 ATM 并为每个 ATM 的 AverageElectricity 调用此 WCF。 (只是意识到我的意思是报告所有 ATM,而不是报告 1 个 ATM。原始问题中没有提到)
    • 好吧,只是玩弄可能的 WCF 调用。你可以有两个调用,比如 DtoRequestedCalculations CalculateStatisticalValuesOverMultipleAtms(List atmIds, List calculateIdentifiers) 和我上面的答案中的一个。 .
    • 谢谢,我现在有一些想法可以让我找到正确的方向!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多