Last changed: 21 February 2017

About the client data layer

Swedish Species Information Center has created a client data layer for internal use. Those who want to use the web services in ArtDatabankenSOA may choose to use our client data layer. This client data layer is plattform specific and uses Microsoft .NET Framework version 3.5. The data layer consists of some Dynamic-link libraries (DLL) and can be downloaded from the following link:

It is optional but recommended to use this client data layer. Last update of these dll's was done 2017-01-30.

The client data layer is used together with web services:

The client data layer is part of the ArtDatabankenSOA.

Benefits when using the client data layer

  • Object oriented: Web services are not object oriented but the client data layer is.
  • Hides communication: Communication is handled by the client data layer.
  • Efficiency: Client data layer handles data efficiently, for example with the help of caching.
  • Shorter development time: A lot of code are already created and tested.

Reference documentation

Detailed documentation available online on address:

Namespaces that describes the client data layer:

  • ArtDatabanken contains functionality that are used in all programs (web services, web applications and windows applications)
  • ArtDatabanken.Data contains the client data layer.
  • ArtDatabanken.Data.DataSource defines interfaces for classes that provides data to the client data layer.
  • ArtDatabanken.WebService.Client contains classes that handles transformation of data and method calls between data model and web service proxies.
  • ArtDatabanken.WebService.Data defines structure of data that web services uses.
  • ArtDatabanken.WebService.Proxy contins classes that acts as proxy to the web services.

Design pattern Onion Architecture

The client data layer is designed according to the design pattern Onion Architecture. Benefits of the Onion Architecture is that it creates a solid foundation for the data model while it still is easy to customize the data handling to each programs requirements. More information about the Onion Architecture can be found on web address

How client data layer fits into client application structure

This picture defines a dependency order among software building blocks from inside to outside of the onion. For example: I/O has knowledge about the data model but the data model does not know anything about I/O or the application code.

Implementation of the data model and data management services

Types of classes and interfaces in the client data layer

  • Data: These classes and interfaces represent the actual data, for example interface IRegion.
  • Data list: Collections of data of the specified type, for example class RegionList.
  • Data search criteria: Each search criteria interface is related to a specific data type and contains search criterias specific to that data type, for example interface IRegionSearchCriteria is used to search regions.
  • Data managers: One manager interface for each type of data, for example interface IRegionManager handles regions. Implementation of these managers interfaces are the starting point when data are retrieved.
  • Entry point to data managers: The static class CoreData acts as entry point to all data manager interfaces.
  • Data source: Each data source handles one type of data and provides the manager of the same data type with data.

The "Data Model" part of the Onion Architecture consists of classes and interfaces of type data, data list and data search criteria. The "Data Management Services" part of the Onion Architecture consists of classes and interfaces of type data source, data manager and entry point to data managers.

Flexible solution

Classes of type data, data search criteria, data managers and data source are defined and handled by interfaces. This implies that you can define your own implementation of these interfaces and use it in the data model.

Caching data

Data is cached for efficiency reasons. What type of data that you want to cache varies depending on the type of client application. Data caching is turned on by using a data manager implementation that supports caching of desired data. Data managers with caching featuers in the client data layer come in pairs. For example LocaleManagerSingleThreadCache and LocaleManagerMultiThreadCache. Which one to choose depends on if your client application must cope with multiple users or threads.

Example: CoreData.LocaleManager = new LocaleManagerMultiThreadCache();

This code sets a locale manager that caches locales and handles multiple parallel calls.

User session

Each user of the client data layer must login before any other methods in the client data layer are called. Login is made to one of the methods CoreData.UserManager.Login(...). The login method returns an IUserContext. This user context must be keept by the client application as long as the user uses the client application. Several methods in the new client data layer require a user context. The user context contains information about the user rights and preferences. When the user has finished using the client application a call to the method CoreData.UserManager.Logout(IUserContext) should be made.

User context

The interface IUserContext defines properties and methods that are used to:

  • Identify the user that is logged in.
  • Identify the user rights in relation to currently used appplication.
  • Contains user preferences (language and role that the user currently wants to use).
  • Handle transactions.
  • Storage of temporary (session scope) user related data.

An instance of a class that implements IUserContext is returned as a result of a successful login. The user context should not be used anymore after the user has logged out from the client data layer.

Transaction handling

How transaction handling works:

A transaction starts with a call to the method IUserContext.StartTransaction which has an optional parameter that specifies a timeout limit. If data are successfully updated the client makes a call to the methodITransaction.Commit. If something goes wrong in data handling the client makes a call to methodITransaction.Rollback. The implementation of ITransaction.Dispose makes a call to ITransaction.Rollback if the transaction is not already terminated.

Virtual transaction:

Transaction handling is done with the help a virtual transaction. A virtual transaction is simply a statement that the user has started a transaction. Real transactions are made against real data sources and the "Data Model" and "Data Management Services Part" of the Onion Architecture does not know anything about the real data sources. All real transactions are commited when the virtual transaction is commited.

Example code:

IUserContext userContext = GetCurrentUsersContext(); using (ITransaction transaction = userContext.StartTransaction()) {     // Update data.

    transaction.Commit(); } This creates a virtual transaction that is referenced by the variable transaction. Transaction information is also stored in the user context. IUserContext.Transaction contains the virtual transaction.IUserContext.Transactions contains the real transactions against data sources.  Each data source, that handles transactions, must always check for possible transactions when they are accessed. If a data source is called during a virtual transaction a real transaction against that data source must be created. Only one transaction against a web service should be created during a virtual transaction. The interface ITransactioncontains the property DataSourceInformation. This information can be used to verify if the web service already has a real transaction associated with the virtual transaction.

Multiple transactions:

There is no support for distributed transactions. Transactions against more than one data source may be performed but there is no guarantee of atomic operation. One transaction may fail but another may succeed.

Why both data manager and data source for each data type?

The division in data manager and data source for each type of data is in order to facilitate if you want to manage data from another data source. A data source has a minimum of methods to handle the data type in contrast to the data manager that may contain several methods that can be helpful to use in a client application. Caching is handled in the data managers this implies that you don't have to deal with caching when implementing data handling to a different data source.

Web Service Connections

The "Web Service Connection" part of the client application structure is divided into three different parts:

  • Namespace ArtDatabanken.WebService.Client contains classes that handles transformation of data and method calls between the data model and web service proxies. Each web service has a data source class that handles login/logout and configuration of data sources in the data manager classes, for example classArtDatabanken.WebService.Client.GeoReferenceService.GeoReferenceDataSource. Each data type that a web service handles has a data source class that implements the data source interface as defined by the data model, for example classArtDatabanken.WebService.Client.GeoReferenceService.RegionDataSource implements the interface ArtDatabanken.Data.DataSource.IRegionDataSource.
  • Namespace ArtDatabanken.WebService.Data defines structure of data that web services uses.
  • Namespace ArtDatabanken.WebService.Proxy contins classes that acts as proxy to the web services. Each web service has one proxy class. For example class GeoReferenceServiceProxy acts as a proxy to the web service GeoReferenceService. The proxy class is used to hide connection handling from rest of the code.


The client data layer must be configured before it can be used.

Configuration steps:

  1. Set data source in all data managers that the client application uses. Data managers are accessed using the properties of the static class CoreData. Notice that UserDataSource must be hooked up before any other data sources. This is because the UserDataSource handles login/logout of users and all other data sources may depend on an existing implementation of the IUserDataSource when they are hooked up.

Example of configuration code:


Explenation of source code:

  1. Line 1 to 4: Web services are hooked up as data sources in the Onion Architecture. Notice that UserDataSource must be hooked up before any other data sources.
using ArtDatabanken.Data;
using ArtDatabanken.WebService.Client.AnalysisService;
using ArtDatabanken.WebService.Client.GeoReferenceService;
using ArtDatabanken.WebService.Client.ReferenceService;
using ArtDatabanken.WebService.Client.SpeciesObservationService;
using ArtDatabanken.WebService.Client.TaxonAttributeService;
using ArtDatabanken.WebService.Client.TaxonService;
using ArtDatabanken.WebService.Client.UserService;

namespace TutorialSimple
    // Include dll from zip-file
    class Program
        static void Main(string[] args)
            ICoordinateSystem coordinateSystem;
            ISpeciesObservationSearchCriteria speciesObservationSearchCriteria;
            ITaxonSearchCriteria taxonSearchCriteria;
            IUserContext userContext;
            SpeciesObservationList speciesObservations;
            TaxonList taxa;

            // Configure data sources in the Onion architecture.
            // User service must be first because the other services depends on UserService.

            // Data is accessed with usage of manger classes in the static class ArtDatabanken.Data.CoreData.

            // Login to the web services.
            // All real applications should have their own application logins.
            // These application logins are requested from Björn Karlsson (
            userContext = CoreData.UserManager.Login("HackForSwedenUser", "Hack4Swe2", "HackForSweden");

            // Search for species by name search string.
            taxonSearchCriteria = new TaxonSearchCriteria();
            taxonSearchCriteria.IsValidTaxon = true;
            taxonSearchCriteria.TaxonNameSearchString = "trumgräshoppa";
            taxa = CoreData.TaxonManager.GetTaxa(userContext, taxonSearchCriteria);

            // Get species observations for received taxa.
            coordinateSystem = new CoordinateSystem();
            coordinateSystem.Id = CoordinateSystemId.SWEREF99_TM;
            speciesObservationSearchCriteria = new SpeciesObservationSearchCriteria();
            speciesObservationSearchCriteria.IncludePositiveObservations = true;
            speciesObservationSearchCriteria.TaxonIds = taxa.GetIds();
            speciesObservations = CoreData.SpeciesObservationManager.GetSpeciesObservations(userContext, speciesObservationSearchCriteria, coordinateSystem);