Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3 tiers nhibernate + wcf + Silverlight

Recently I was asked to develop a project. The architecture looks like:

  • 1 tier: DataAccess base on Nhibernate
  • 2 tier: Business layer based on WCF service and some Core classes
  • 3 tier: View based on Silverlight

I am going to use DTO objects to pass data between 2nd and 3rd tier.

I have realized that the project will have huge domain model and a lot of business entities should support standart and custom CRUD operations. On the first tier it will be solved by generic NHibernate Repository + Specification.

But 2nd tier (one WCF service) will look like set of methods which provides custom and standart CRUD interface of DTO to 3rd tier.

For example model looks like:

class Product {}
class Category {}

DTOs:

class ProductDTO {}
class CategoryDTO {}

"problem" WCF Service:

public class DataService
{
  public List<CategoryDTO> GetAllCategories()
  {
  }

  public List<ProductDTO> GetAllProducts()
  {
  }
}

possible solution:

public class ProductDataService
{
  public List<ProductDTO> GetAllProducts()
  {
  }
}

 public class CategoryDataService
{
  public List<CategoryDTO> GetAllCategories()
  {
  }
}

Questions:

  1. Is there any good alternatives for the solution listed above?
  2. Is there any "generic" way that can be used in WCF service for this situation ?
like image 336
Alexandr Avatar asked Jan 23 '13 15:01

Alexandr


2 Answers

Is there any good alternatives for the solution listed above?

Yes, you can use RESTfull service. I would also recommend against using fat interfaces (mathieu solution). Fat interfaces are hard to maintain, refactor, they are bulky and heavy. If you go for REST you can have such APIs as (similar interface you can have in WCF):

  • Category

    • GET all: http://myservice.com/api/categories
    • GET one: http://myservice.com/api/categories/123
    • POST one: http://myservice.com/api/categories/add
    • PUT/PATCH one: http://myservice.com/api/categories/update
    • DELETE one: http://myservice.com/api/categories/delete/123
  • Likewise for the Product

    • GET all: http://myservice.com/api/products
    • GET one: http://myservice.com/api/products/123
    • POST one: http://myservice.com/api/products/add
    • PUT/PATCH one: http://myservice.com/api/products/update
    • DELETE one: http://myservice.com/api/products/delete/123

Is there any "generic" way that can be used in WCF service for this situation ?

Yes, you can use generics on the server, but to the client this will appear as a concrete type. See this post for an example.

like image 62
oleksii Avatar answered Sep 20 '22 12:09

oleksii


Assuming you're talking purely about CRUD on "Reference" data (categories, products, and so on), you should have 1 service with lots of GetAllXXX methods or multiple services, eventually inheriting from a base one. It really doesn't matter, as if you have many DTOs to transfer, you will get lots of GetXXX methods.

Just be aware of those 2 points :

  • higher number of methods in wcf service, higher "warmup" time (this issue arises with around 100-200 methods (1)
  • wcf cannot expose "generic" methods without the generic parameter defined

For example :

public class DataService<TIn>
{
    protected List<TOut> GetAll<TOut>()
    {
         // handle generic loading and transformation here
    }
}

public class CategoryService : DataService<Category>
{
    public List<CategoryDTO> GetAllCategories()
    {
        return GetAll<CategoryDTO>();
    }
}

or

public class DataService
{
    protected List<TOut> GetAll<TIn, TOut>()
    {
         // handle generic loading and transformation here
    }

    public List<CategoryDTO> GetAllCategories()
    {
        return GetAll<Category, CategoryDTO>();
    }
}

Then inside the generic method you can map from Category to CategoryDto using Automapper, for example.

Finally, for more user/business oriented services, you should have DTOs specific to the data you will present in each "View".

(1) yes, it is very much from an OOP perspective. But you tend to reach those issues with code generation from large databases :)

like image 41
mathieu Avatar answered Sep 20 '22 12:09

mathieu