Question

What are your favorite ways to encapsulate LINQ to SQL entity classes and data-context classes into business objects?

What have you found to work in a given situation?

Have you invented or taken to any specific patterns?

Was it helpful?

Solution

I've found a pattern which I think works best--In my case, at least.


I extend entity classes using partial classes. I use partial classes so the signature of the entity does not change (see the DeleteOnSubmit call in the Delete method).

I've cooked up a a small example. Here's an image of the database and LINQ to SQL class setup:



And here's the partial class in which I implement business logic:

/// <summary>
/// This class extends BusinessLogicDataContext.Products entity class
/// </summary>
public partial class Product
{
    /// <summary>
    /// New up a product by column: dbo.Products.ProductId in database
    /// </summary>
    public Product(Int32 id)
    {
        var dc = new BusinessLogicDataContext();

        // query database for the product
        var query = (
            from p in dc.Products 
            where p.ProductId == id 
            select p
        ).FirstOrDefault();

        // if database-entry does not exist in database, exit
        if (query == null) return;

        /* if product exists, populate self (this._ProductId and
           this._ProductName are both auto-generated private
           variables of the entity class which corresponds to the
           auto-generated public properties: ProductId and ProductName) */
        this._ProductId = query.ProductId;
        this._ProductName = query.ProductName;
    }


    /// <summary>
    /// Delete product
    /// </summary>
    public void Delete()
    {
        // if self is not poulated, exit
        if (this._ProductId == 0) return;

        var dc = new BusinessLogicDataContext();

        // delete entry in database
        dc.Products.DeleteOnSubmit(this);
        dc.SubmitChanges();

        // reset self (you could implement IDisposable here)
        this._ProductId = 0;
        this._ProductName = "";
    }
}

Using the implemented business logic:

// new up a product
var p = new Product(1); // p.ProductId: 1, p.ProductName: "A car"

// delete the product
p.Delete(); // p.ProductId: 0, p.ProductName: ""

Furthermore: LINQ to SQL entity classes are very open in nature. This means that the property corresponding to the dbo.Products.ProductId column implements both a getter and a setter--this field should not be changeable.

To my knowledge you can't override properties using partial classes, so what I usually do is implement a manager which narrows the object using an interface:

public interface IProduct
{
    Int32 ProductId { get; }

    void Delete();
}

OTHER TIPS

I tend to use the Repository pattern to encapsulate DataContexts.

Repository Pattern

I would like to find a better way to emit POCO objects from my data layer while using LINQ2SQL though.

I just published a sample of how you can structure your application that uses Linq to Sql for storage, using IoC and T4-templates.

http://daniel.wertheim.se/2010/03/14/linq-to-sql-how-to-separate-the-entities-and-the-datacontext/

Right now I'm trying to use LINQ to SQL entity classes as business objects, to pass them around between functions and services.

Of course, you should have separate entity classes for database access, so your database layout can change without changing the business objects!

I'd be most interested in a good solution for this, too!

Check out the source code for the MVC Sample app that Rob Conery is putting together:

http://www.codeplex.com/mvcsamples/

He has a separate entity layer that maps to the LINQ to SQL classes.

I did some experimentation using Entity Framework and Linq to Entities as a way to further separate my client code from the database, but I found it clumsy to use and was worried about the performance.

In my current project I use Linq to SQL as my data layer, but have separate classes where I implement all Linq queries. The classes return entities defined in my Linq to SQL context, but the queries are hidden in methods.

I found the articles by Ian Cooper on CodeBetter.com and Stephen Walther series invaluable in understanding the need to write the POCO entities first and then map them to the database rather than doing it the other way around (which is what I always used to do).

I'm playing around with the idea to have a separate layer of OO model (better support for OO practices), but that use LINQ to SQL under the hood. The idea is to have an xml file that a custom tool will use to generate the code. Since LINQ to SQL entites are too cluttered for my preferences, I will auto-generate new classes to use as my entities and of course the DataContext will be completely hidden for the client code. Do the short answer is: Create new entity classes but use the underlying LINQ to SQL entities and DataContext.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top