views:

30

answers:

2

If it's important to keep data access 'away' from business and presentation layers, what alternatives or approaches can I take so that my LINQ to SQL entities can stay in the data access layer?

So far I seem to be simply duplicating the classes produced by sqlmetal, and passing those object around instead simply to keep the two layers appart.

For example, I have a table in my DB called Books. If a user is creating a new book via the UI, the Book class generated by sqlmetal seems like a perfect fit although I'm tightly coupling my design by doing so.

A: 

What I do is to have all my DataAccess (LINQ-to-SQL in your case) in one project and then I have another business project which uses the DataAccess project, thereby segrating the DataAccess project form the UI layer.

In your example for books, my business layer would have a class called Book:

public class Book
{

    private IAuthorRespository _authorRepository = new LinqToSqlAuthorRepository();
    private IBookRespository _bookRepository = new LinqToSqlBookRepository();

    public int BookId { get { return _bookId; }}
    private int _bookId;

    public virtual string BookName{get;set;}
    public virtual string ISBN {get;set;}
    // ...Other properties

    public Book()
    {
        // When creating a new book
        _bookId = 0;
    }

    public Book(int id)
    {
        // For an existing book
        _bookId = id;
        Load();
    }

    protected void Load()
    {
        BookEntity book = _bookRepository.GetBook(BookId);
        BookName = book.BookName;
        ISBN = book.ISBN;
    }

    public void Save()
    {
        BookEntity book = MapEntityFromThisClass();
        _bookRepository.Save(book);
    }

    public Author GetAuthor()
    {
        return _authorRepository.GetAuthor();
    }

}

This then means that your UI is totally separated from the actual data access and that all of your Book logic is contained sensibly within a class.

You can make this further separated by using IoC with a system such as Microsoft Unity or Castle so that you don't have to write = new LinqToSqlXYZ(); and can instead write something along the lines of IoC.Resolve<IBookRepostory>(); (depending on your implementation). This then means your Book class is not tied down to LINQ-to-SQL anymore either.

GenericTypeTea
A: 

Linq to Sql offers a 1:1 mapping between entities and your database tables. It could be argued that the entities themselves are a level of abstraction away from the database, and that is what you are tied down to.

If you are making a 1:1 duplication of the entities offered up by linq to sql, then it may mean that its not worth having them there, because you are still just as tied to those classes as you are to the entities offered by linq to sql.

By creating another layer, you are also elminating the benefits of change tracking provided by linq to sql, meaning you have to copy any changes from your classes into the entities provided by linq to sql to perform data operations.

If you would like to abstract away the DataContext type code from any presentation or business layers, and control the interface to your data more tightly, then the repository pattern is good. You can always have your repository return the entity types created by linq to sql, which means you are not duplicating types, you also get change tracking, but you are still keeping the code that controls the DataContext inside the repository.

You may consider projecting the data into a different class for the benefit of your presentation (a view model), or business logic. This is the route I tend to go down, if I want to use linq to sql, but I don't want a 1:1 mapping between the entities and my view models.

SteadyEddi