Advice on approach to organizing my business logic & data access? I've been researching various patterns for structuring my business logic &amp; data access, particular in the context of C# and the Entity Framework. I've come up with a basic idea of how I think I'd like to do it, based on several SO answers:


https://stackoverflow.com/questions/1169188/ef-objectcontext-service-and-repositry-managing-context-lifetime
https://stackoverflow.com/questions/678922/using-transactions-with-business-processes-and-the-repository-pattern


I envision a UnitOfWork that encapsulates an IObjectContext (abstract so I can swap out contexts for testing), and exposes a repository of IQueryable&lt;TEntity&gt;.

interface IUnitOfWork
{
    private IObjectContext _context;

    public void SetupContext(); // Create object context here

    IQueryable&lt;TEntity&gt; Repository&lt;TEntity&gt;() 
            where TEntity : class, IEntityWithKey;
}


I intend to write service classes that contain my business logic, and follow this structure:

class MyService : IService
{
    public DoWork()
    {
        // Same as nesting one using within the other
        using( IUnitOfWork unitOfWork = unitOfWorkFactory.Create() ) 
        using( TransactionScope tScope = new TransactionScope() )
        {
            var repository = unitOfWork.Repository&lt;TEntity&gt;(); 

            /* Do some work with repository */

            unitOfWork.Commit(); // Save changes
            tScope.Complete(); // End transaction
        }
    }
}


Am I going crazy with design patterns? Is there a better way to do this?
By reviewing this I have two general comments to your code:

Transaction

Is there any reason to use explicit transaction scope? When you call SaveChanges on the context it already uses transaction. It either uses ambient transaction or create a new one database transaction. So unless you are using multiple transactional resources (multiple database connections, MSMQ, etc.) or calling SaveChanges multiple times you don't need to create transaction explicitly. It is point of unit of work to save changes as one atomic unit. Also one side note: Default transaction used in SaveChanges uses default (or current) isolation level configured on database connection. Default for SQL Server is ReadCommitted. Default isolation level for TransactionScope is Serializable.

Testing

You mentioned that you want to make this abstraction to be able to replace context for testing. If you mean unit testing you can stop and go back to redesign your interfaces. You cannot unit test your business layer code if it uses IQueryable (Linq-to-entities) exposed by your data access layer. There is currently no provider which can simulate linq-to-entities behaviour for your unit tests. Once you use same in memory collection to mock IQueryable you will use linq-to-objects in your unit tests instead. That means you will test different code. 

The only correct way is either:


Not expose IQueryable from your DAL. Keep all linq-to-entities queries as internal implementation of your repositories (= you must materialize result in repositories by for example calling .ToList).
Use integration tests against real test database instead of using unit tests with mocked data access layer


I wrote several answers about this problematic on Stack Overflow:


Unit testing DbContext
Using the repository pattern to support multiple providers


Check also linked answers in those questions.