views:

614

answers:

4

Hi there,

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

+1  A: 

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.

Michael Maddox
A: 

The classes generated by the linq2sql designer are partial classes, so you can extend these and put your business logic directly into them. The idea is that linq is used to persist/reconstruct these entities so you can avoid the kind of mapping you're talking about.

Lee
Once you start embedding business logic into the LinqToSql partial classes, it is very tough to decouple them later. If you don't want/need a business layer, that's fine, but that is not always the correct way to go. Also, it's hard to replace LinqToSql with a different ORM with a different feature set at some point in the future (which may or may not be necessary).
Michael Maddox
The point is, your linqToSql entities are part of the 'business layer' and the repository is used to fetch/persist them in the databaase. Yes there is some coupling to the linq designer but that's a different issue.
Lee
@Lee: no, you shouldn't use linq2sql for your business layer. It's a WONDERFUL object relational mapper, but I would strongly encourage you to not fall into that trap. Your data base is a normalization of data, your business layer is a normalization of behaviors.
Amir
+2  A: 

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.

Michael Mann
+4  A: 

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...

Amir
I love this idea... the only problem is in MVC, the controllers cannot take in interfaces for the add methods. This makes the interfaces relatively useless for MVC. How have you handled this problem, because I really would like to do this.
Matthew Kruskamp
add method? can you elaborate, i'm currently using this appraoch with aspmvc and haven't had any problems.
Amir
"the controllers cannot take in interfaces for the add methods", just create a view model that implements the interface. It can reside in the web project as it's only an object to help facilitate interactions with the View.
Amir