Search code examples
c#.netdatabaselinqseparation-of-concerns

How do you keep your Domain Logic seperate from DB/Persistence Logic with Linq-2-Sql?


I'm trying to get at the best way to seperate the concerns of my domain logic and my persistence logic. I'm using Linq-2-Sql for the data access and I've been following the NerdDinner tutorial. If you look at page 40, you can see they are using partial classes to business rules to their Linq generated classes. To me, that feels wrong (is it?) and I'd like to have my own POCOs that are exposed to the presentation tier of my application. It looks like one option here, is to use a seperate DTO class. That feels better to me but it adds a lot more code to test and maintain.

I like the simplicity of simply adding partial classes to enforce business rules on the Linq classes, but I don't like exposing the Linq classes to my presentation tier, since if the database changes I'll need to update the presentation tier as well.

The DTO approach feels cleaner, since I'd never need to update the presentation tier if the database changes, but it is a lot more code to deal with.

My current approach is thus, two Class Libraries one with Linq-2-Sql DBML + Partial Classes, and the second with a set of classes that have nothing but auto-generated properties and then a "repo" class that manages getting data from the Linq assembly and converting it to IQueryable<T>.

Is there a better way? Is there a better middle ground? Can I take the best of both worlds? If so, how would you seperate them into different assemblies?

update

Maybe, what I really need to do is consolidate all of the Persitence/Domain logic into a single assembly (the same approach used in the NerdDinner sample), and then create different "View Objects" in my presentation tier, that are denormalized versions of my Linq-2-Sql Entities?


Solution

  • I try to keep my domain objects as persistence ignorant as the technology that I'm using will allow. For LINQ to SQL, I followed the approach set out by Ian Cooper (see Being Ignorant with LINQ to SQL, Architecting LINQ to SQL Applications, Part 5 and Architecting LINQ to SQL Applications, Part 6). Basically, you can manually code up your domain objects and wire them up to LINQ to SQL using sqlmetal to generate the mapping to the database which you can then hand edit to suit your needs. It's worked quite well for me.

    Jeremy Miller has a good article on the topic of persistence ignorance in MSDN magazine. See The Unit Of Work Pattern and Persistence Ignorance.

    My current approach is thus, two Class Libraries one with Linq-2-Sql DBML + Partial Classes, and the second with a set of classes that have nothing but auto-generated properties and then a "repo" class that manages getting data from the Linq assembly and converting it to IQueryable<T>.

    I don't like this approach. It violates DRY so violently.