Shackles
Shackles

Reputation: 1264

Repository Pattern with Linq to SQL: Many-to-Many relationships

I am working on a project following the suggested repository pattern in Steven Sanderson's excellent book "Pro ASP.NET MVC 2 Framework".

Take the following example: I have a table for "Products" and for "Images". Both have an own repository that creates a new DataContext in the constructor. Now, I want to establish a many-to-many relationship between the two entities called "ImagesForProducts".

Should I create a separate repository for the ImagesForProducts entities? If so, how can I share the DataContext between all the entities? In that case I have to instantiate my ProductController with two repositories (for Products and for ImagesForProducts), right?

I'd rather access the images using my product instances, so that I can write myProduct.AddImage(img). But how can I persist the relation in the database using the ProductRepository?

As you can see, I am not sure about the overall architecture and would highly appreciate a basic code example.

Thanks in advance!

Upvotes: 2

Views: 919

Answers (2)

Shackles
Shackles

Reputation: 1264

After some careful research and consideration, I decided to let the repositories handle image attachments instead of the product instances (mostly because the instances shouldn't deal with any database related stuff).

I already got an ImagesForProducts entity because I am using Linq-to-SQL mapping. I therefore added a Table of that type to my product repository which I can initiate with the current DataContext of the product repository. That way, both instances always use a shared DataContext and I can simply implement a method "AttachImageToProduct" like this:

public class MsSqlProductsRepository : MsSqlRepository<Product>, IProductsRepository
{
    protected Table<ImagesForProducts> imageRelationsTable { get; set; }

    public MsSqlProductsRepository(string connectionString)
        : base(connectionString)
    {
        imageRelationsTable = DataContext.GetTable<ImagesForProducts>();
    }

    public void AttachImageToProduct(Image image, Product product)
    {
        if (imageRelationsTable.First(r => r.ImageId == image.Id && r.ProductId == product.Id) != null)
            return;

        ImagesForProducts rel = new ImagesForProducts();
        rel.ImageId = image.Id;
        rel.ProductId = product.Id;

        imageRelationsTable.InsertOnSubmit(rel);
        entitiesTable.Context.SubmitChanges();
    }
}

Do you have any general concerns about this solution?

Upvotes: 1

Faris Zacina
Faris Zacina

Reputation: 14274

The repository pattern should be used to represent an in-memory store for your domain objects. Since you want your domain model to be ignorant of the persistence internals and also have everything designed around aggregate roots, then it does not make sense to have a ImagesForProducts entity and thus doesn't make sense to have a separate repository for ImagesForProducts entities.

First of all I Would recommend building your domain model with POCO objects that can be used in any persistence scenario (LINQ to SQL, EF, Stored Procedures..). You should have only two repositories (ProductRepository and ImageRepository) and resolve the many to meny relation as "relational" properties in both domain objects. For example you can add an Image collection to the Product domain object and a Product collection to the Image domain object. Once you build your POCO objects, then you can handle mappings to the specific persistence store inside your repositories (preferrably in the constructor).

Once you implement the plubming, you can and add an image to the product:

product.Images.Add(image);

Then you can call your repository like this:

productRepository.Add(product);

Upvotes: 0

Related Questions