2010-12-18 14 views
2

Ich arbeite an einem Projekt, das dem vorgeschlagenen Repository-Muster in Steven Sandersons ausgezeichnetem Buch "Pro ASP.NET MVC 2 Framework" folgt.Repository-Muster mit Linq zu SQL: Viele-zu-viele Beziehungen

Nehmen Sie das folgende Beispiel: Ich habe eine Tabelle für "Produkte" und für "Bilder". Beide haben ein eigenes Repository, das im Konstruktor einen neuen DataContext erstellt. Nun möchte ich eine Viele-zu-Viele-Beziehung zwischen den beiden Entitäten "ImagesForProducts" herstellen.

Sollte ich ein separates Repository für die ImagesForProducts-Entitäten erstellen? Wenn ja, wie kann ich den DataContext zwischen allen Entitäten freigeben? In diesem Fall muss ich meinen ProductController mit zwei Repositories instanziieren (für Produkte und für ImagesForProducts), oder?

Ich würde lieber auf die Bilder mit meinen Produktinstanzen zugreifen, so dass ich myProduct.AddImage (img) schreiben kann. Wie aber behalte ich die Beziehung in der Datenbank mit dem ProductRepository?

Wie Sie sehen können, bin ich mir über die Gesamtarchitektur nicht sicher und würde ein grundlegendes Codebeispiel sehr schätzen.

Vielen Dank im Voraus!

Antwort

1

Nach einiger sorgfältiger Recherche und Prüfung, Ich entschied mich dafür, dass die Repositories Image-Attachments anstelle der Produktinstanzen verarbeiten sollten (hauptsächlich, weil die Instanzen sich nicht mit Datenbank-verwandten Dingen beschäftigen sollten).

Ich habe bereits eine ImagesForProducts-Entität, weil ich Linq-to-SQL-Mapping verwende. Daher habe ich meinem Produkt-Repository eine Tabelle dieses Typs hinzugefügt, die ich mit dem aktuellen DataContext des Produkt-Repository initiieren kann. Auf diese Weise verwenden beide Instanzen immer einen gemeinsamen Datacontext und ich kann einfach eine Methode „AttachImageToProduct“ wie folgt implementieren:

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(); 
    } 
} 

Haben Sie allgemeine Bedenken zu dieser Lösung?

0

Das Repository-Muster sollte verwendet werden, um einen speicherinternen Speicher für Ihre Domänenobjekte darzustellen. Da Ihr Domänenmodell die persistenten Interna nicht kennen sollte und auch alles um Aggregat-Roots entworfen wurde, macht es keinen Sinn, eine ImagesForProducts-Entität zu haben, und daher ist es nicht sinnvoll, ein separates Repository für ImagesForProducts-Entitäten zu haben.

Zunächst würde ich empfehlen, Ihr Domänenmodell mit POCO-Objekten zu erstellen, die in jedem Persistenzszenario verwendet werden können (LINQ to SQL, EF, Stored Procedures ..). Sie sollten nur zwei Repositorys (ProductRepository und ImageRepository) haben und die Beziehung von vielen zu meny als "relationale" Eigenschaften in beiden Domänenobjekten auflösen. Sie können zum Beispiel dem Produktdomänenobjekt eine Imagesammlung und dem Image-Domänenobjekt eine Produktsammlung hinzufügen. Sobald Sie Ihre POCO-Objekte erstellt haben, können Sie Zuordnungen zu dem spezifischen Persistenzspeicher innerhalb Ihrer Repositories (vorzugsweise im Konstruktor) handhaben.

Sobald Sie die plubming implementieren, können Sie und ein Bild auf das Produkt hinzufügen:

product.Images.Add(image); 

Dann Sie Ihr Repository wie folgt aufrufen können:

productRepository.Add(product); 
+0

Danke für Ihre Antwort. Der Linq-Mapper gibt mir bereits eine ImagesForProducts-Entity, die mich nicht betrifft, da sie nur in Linq-bezogenen Repositories verwendet wird und für meine Modelle nicht wesentlich ist. – Shackles