Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion between DTOs (linq2sql) and Class objects!

i have been successfully working with linq2sql and the linq DTOs (the classes that are created by linq2sql) ....

I am confused, i have the task of updating an old application and i can see that my DTOs will be used how they should be .... to transport date

I am using the repository pattern so i am passing data from the repository to the service via the linq2sql dtos... once i am in the service layer (this is basically my business logic) then I need to pass around class objects ..

these class objects are basicaly a mirror image (more or less) of the dtos - there are some changes in some place but generally the same..

So getting back to the question in hand! -- is this good practice to use dtos only to transport data from repository to service layer ... and once in the service layer(business logic) i should but MAPPING all my dtos to there class object counter parts (of course using automapper!!)

My other alternative is to continue to use the DTOS like class objects and pass them around from method to method and as return types etc but i feel this is bad practice and i keep going round in circles wondering which method i should apply?

Any help really appreciated

thanks

like image 246
mark smith Avatar asked Aug 24 '09 15:08

mark smith


3 Answers

Here is my opinion: When dealing with any non-trival application. Using your linq2Sql objects as your domain model is a really bad idea. I see linq2Sql as an ORM and nothing more. Databases (which linq2Sql has a direct correspondance to) is a normalization of data. Classes (in the OOAD sense) are a normalization of behavior (not data).

[these class objects are basicaly a mirror image]...

I encountered this when building applications with linq2Sql. Lets be realistic....most line of business applications are glorified CRUD applications. So it isn't out of the question that a large percentage of your application's entities will correspond directly to database tables. I didn't want to be bound directly to the DTO's that were generated, but at the same time I didn't want duplicated classes littered across my application.

So here is my solution:
I "programmed to an interface".

Lets say I have a PersonDto (Dto standing for Data Transfer Object) with properties of FirstName, LastName, Age (which relate directly to database columns).

I created an IPerson interface and had my PersonDto implement it.


  [Table(Name="Persons")]
  internal class PersonDto : IPerson
  {
      ....
  }

And my repository method would take in and retrieve IPerson as opposed to the Linq2Sql class.


    IPerson somePerson = _repository.Get(someGuid);
    somePerson.FirstName = "SomeName";
    _repository.Save(somePerson);

This approach has worked really well for me. Whenever I feel I need to deviate from the DTO, I can do so fairly easily because of the interface representing my object as opposed to the DTO.

Some general pointers: Build your DTO's by hand...I know it sounds crazy, but you'll find that it works really well with a top down, test driven development approach. Your DTO's (linq2Sql) objects will be extremely light and will be open to changes outside of the .dbml designer.

Keep your DTO's and DataContext's internal. There is no reason for your dto's to be exposed publicly (given that you have public interfaces for you repositories and domain objects). Doing this will force a logical separation between your domain model and data access.

Put all of your data access layer in a separate project (again to enforce this separation).

Put your interface declarations in a separate project (this will ensure you don't run into any circular references).

Hope this helps...

like image 62
Amir Avatar answered Oct 18 '22 22:10

Amir


I actually had a similar question on this topic although my intent was slightly different. The recommendation was to use the Linq2SQL classes as the domain objects and to take advantage of partial classes as others have mentioned. My main concern came with the shape of those objects (ie property names), and the accessibility of class members (ie private v.s. protected for example).

The shape of the objects and even the accessibility can be addressed by using t4 templates where Damien Guard has put together a T4 template to allow you to control the shape of the classes that Linq2Sql would generate for you. This can be seen here T4 template for Linq2SQL.

This is the approach that I am going to look into and see if it addresses my concerns. Additionally if your service layer can accept interfaces to method arguments you can also control what the service layer has access to through interface wrappers around your Linq2SQL DTOs.

Hope this helps.

like image 24
Michael Mann Avatar answered Oct 18 '22 23:10

Michael Mann


This is one of the best discussions of the topic that I've seen:

http://blog.wekeroad.com/blog/linqtosql-momma-said-knock-you-out/

In the end, coupling and cohesion decisions are situational and you have to decide what is best for your situation.

When your application outgrows LinqToSql, how easy will it be to yank out LinqToSql and insert another ORM in it's place? That is something you have to give serious thought to.

In general, minimize the knowledge your business layer has about LinqToSql. LinqToSql should be completely hidden from your UI layer (your business layer makes up a good chunk of this shield). It's very easy to go down the wrong architectual path with LinqToSql and it can be very difficult to get back on the right path after the fact.

like image 34
Michael Maddox Avatar answered Oct 18 '22 22:10

Michael Maddox