views:

1110

answers:

2

I recently started a new webforms project and decided to seperate the business classes from any DBML references. My business layer classes instead access discrete Data layer methods and are returned collections of DTO's. So the data layer might project DTO's like the following:

(from c in dataContext.Customers
where c.Active == true 
select new DTO.Customer
{
   CustomerID = c.CustomerID,
   Name = c.CustomerName,
   ...
}).ToList()

Although building the DTO objects adds work, this feels like a better approach to a tight binding between Business & Data layers and means I can test the Business layer without a database being present.

My question is, is this good practice?, Is there a way of generating the DTO's (maybe via SQLMetal), and what other problems might I strike as the project progresses.

A: 

In my opinion in most cases DTO objects are not needed when dealing with LINQ. Generated LINQ classes can be easily tested. LINQ gives you ability to query your data from different sources using identical queries. It gives you ability to test your queries against lists of objects instead of real db.

aku
Agreed. In essence, your Linq-to-sql objects could be treated as DTOs, and there's even a T4 template for generating your L2S objects as serializable.
mattmc3
+3  A: 

I don't know if it's best practice but I have written similar code in the not so recent past because I too felt that I could improve the separation of concerns by using my own classes instead of the LINQ-designer-generated ones within my application.

You may want to consider just returning an IQueryable<Customer> instead of an IList<Customer> from your data-access method. Since IQueryable<T> inherits from IEnumerable<T> the rest of your app should be able to deal with it quite well. You can also convert it to a List when you really need to.

The advantage of this is that you can dynamically modify your query quite easily and minimze the amount of data returned from SQL Server.

E.g. if your method signature is IQueryable<Customer> GetCustomers() you could get a single customer by calling GetCustomers().Where(c => c.CustomerID == 101).Single();

In this example only one record would be returned from the database whereas I imagine currently your code would return either all customers or you'd be required to write separate methods (and thus very repetitive code) to cater for all the different things you may want to filter by.

BirgerH
I recommend the exact opposite. I wouldn't ever return an IQuerable over an IList outside of the DAL. If you do, then your presentation layer will likely end up executing database queries inadvertently, or you might end up mixing Linq-to-objects calls and get a Linq-to-sql error. Returning IQuerable from Linq-to-sql makes for a really poor and leaky architecture and should be avoided for all but the dinkiest toy applications.
mattmc3