Home > Architecture, Software Factories > Service Factory Modelling Edition – part 2

Service Factory Modelling Edition – part 2

In my last post, I went over a number of issues that my project team and I had with the Service Factory Modelling Edition.

One of the issues was with respect to the generated Entity-to-DataContract translator classes, specifically the fact that the generated class contains no “collection” translation method.

Now, it may seem obvious to some that there is a straightforward way to leverage the generated methods to achieve translation of an entire collection of entities to data collection types, or vice-versa, but not everyone finds it so obvious (at least, some on my project team didn’t find it obvious!! :) )

Ok, lets imagine we have generated a translator class for an Address entity and an AddressDC data contract type. You get the following two static methods (code removed for clarity):

public static BusinessEntities.Address TranslateAddressDCToAddress(DataContracts.AddressDC from)
{
    ...
}
public static DataContracts.AddressDC TranslateAddressToAddressDC(BusinessEntities.Address from)
{
    ...
}

Now, we also have a collection of address entities (stored as a List<Address>), that we want to translate into a collection in our data contract. The data contract has been designed using the modelling tools in the Service Factory, and our AddressDC collection has been modelled as a collection of type List also.

Basically, you loop through the collection you’re translating from and for each record, you call the appropriate translator method, like so:

List<Address> output = new List<Address>();

foreach (AddressDC addressDCItem in AddressDCColl)
{
    output.Add(TranslateBetweenAddressAndAddressDC.TranslateAddressToAddressDC(addressItem));
}

Ok, so the other part of this equation is making sure that we factor this well, and don’t write this code over again everywhere we want to use it. The most logical place to put this is to write it as a new method on the existing translator class.

Of course the thing to remember with this, and this is the issue I really had with the translator generation in the Service Factory, is that the translator is not a partial class, so we have to add code to the existing code file, and because of that, we need to realise that this code will be “removed” again if the translator ever needs to be re-generated.

Obviously we’re likely to want collection translators that go both ways, so there will be two new hand-coded methods. Therefore our final translator would look something like this (again, some of the code has been removed for clarity):

public static BusinessEntities.Address TranslateAddressDCToAddress(DataContracts.AddressDC from)
{
    ...
} 
public static DataContracts.AddressDC TranslateAddressToAddressDC(BusinessEntities.Address from)
{
    ...
}
Public List<Address> TranslateAddressList(DataContracts.AddressDCColl from)
{
    List<Address> output = new List<Address>();
    foreach (AddressDC addressDCItem in from)
    {
        output.Add(TranslateBetweenAddressAndAddressDC.TranslateAddressDCToAddress(addressItem));
    }
    return output;
}
Public DataContracts.AddressDCColl TranslateAddressList(List<Address> from)
{
    DataContracts.AddressDCColl output = new DataContracts.AddressDCColl();
    foreach (Address addressItem in from)
    {
        output.Add(TranslateBetweenAddressAndAddressDC.TranslateAddressToAddressDC(addressItem));
    }
    return output;
}

Please note that this code has been coded off the cuff, and has not been tested, nor even compiled. It’s there just to give you a general idea of what to do.

Mark

  1. July 17, 2008 at 9:27 pm | #1

    Hey…it’s good to know that I could at last find someone who’s into WSSF in NZ. Am wondering if you have taken into account the liabilities as outlined by M/S with using the translators (particularly the third one) – see below:

    Data can be lost between translations when translated data types do not support all of the fields found in the original data types.

    It may be necessary to call multiple translators during a single action, which can increase complexity by requiring process dependencies on consumers of the translator. This can be mitigated by using a process manager pattern.

    Implementation of an object-based solution requires the creation of custom objects that have to be maintained. As the number of data types increase, the maintenance requirements of entity translators will also increase.

    It’s a bit too late in the day for me to think but given that the repository factory (rightly) is pulled out of th WSSF, wondering what tool you are using to codegen the data access side of things.

    Ratnakar

  2. July 17, 2008 at 9:28 pm | #2

    I have hacked the repository factory to work in VS2008 btw.

  3. July 18, 2008 at 11:00 am | #3

    Hi Ratnakar,

    Thanks for your comments…good to hear that you’ve got the respository factory working in VS2008 – I assumed that MS would do so themselves eventually, but for this particular project I wasn’t too worried, since we’d started with VS 2005 in any case.

    So, that is the answer for your question too really – I used the Repository Factory for the data access stuff.

    And yes, I was aware of the limitations/liabilities of using the translators – but they are so simple that it’s pretty easy to work around them in any case. For example, where I had a more entity, with a “parent child” type of relation in there, say a Customer with a collection of Orders as one of its properties, I modified the translator for the Customer so that to translate the Orders property it calls the Orders translators “collection translator” as described in the post above.

    I also had to take into account the fact that where we have data contract types that only have a subset of the fields that the underlying entity have, I compensate for that in the business logic. I’m going to post on that at some point too, but basically for any data that can’t have changed, I make sure the data is left as is in the database.

    My solution here was not ideal, since it results in an additional query on the database, but hey, there are compromises in everything you do, and we decided it was better to do a quick hop to the db again from the services (since the db is “next to” the app server) rather than pass the full state around where its not needed, wasting bandwidth.

    Cheers
    Mark

  4. July 27, 2008 at 12:49 pm | #4

    Cool. I was just raising this with you just in case you weren’t aware.

    I have done something similar with the handling of list translations. I appreciate that you’ve got a blog covering this as you probably would know there’s not enough help available out there.

    Cheers!
    Ratnakar

  1. No trackbacks yet.